Compare commits

..

No commits in common. "main" and "feat/openapi" have entirely different histories.

341 changed files with 8035 additions and 17218 deletions

4
.gitignore vendored
View File

@ -126,7 +126,7 @@ dist
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.openmcp-test
.vscode-test
# yarn v2
.yarn/cache
@ -134,5 +134,3 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.pipeline

BIN
.vitepress/.DS_Store vendored

Binary file not shown.

View File

@ -10,10 +10,6 @@ import { contributors } from './contributors';
import { withMermaid } from "vitepress-plugin-mermaid";
import { customIcons } from './theme/hook/icons';
import enConfig from './i18n/en';
import zhConfig from './i18n/zh';
import jaConfig from './i18n/ja';
export const baseUrl = '/openmcp';
export default withMermaid({
@ -34,14 +30,7 @@ export default withMermaid({
mapAuthors: contributors
}),
GitChangelogMarkdownSection({
excludes: [
'preview/contributors.md',
'zh/preview/contributors.md',
'ja/preview/contributors.md',
'index.md',
'zh/index.md',
'ja/index.md'
]
excludes: ['preview/contributors.md', 'index.md']
}),
ThumbnailHashImages(),
],
@ -76,34 +65,186 @@ export default withMermaid({
head: [
['link', { rel: 'icon', href: baseUrl + '/images/favicon.svg' }]
],
locales: {
root: {
label: 'English',
lang: 'en',
themeConfig: enConfig
},
zh: {
label: '简体中文',
lang: 'zh',
link: '/zh/',
themeConfig: zhConfig
},
ja: {
label: '日本語',
lang: 'ja',
link: '/ja/',
themeConfig: jaConfig
}
},
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: '首页', link: '/' },
{
text: '教程',
items: [
{
component: 'KNavItem',
props: {
title: '简介',
description: '关于 mcp 和 openmcp阁下需要知道的 ...',
icon: 'openmcp',
link: '/plugin-tutorial/'
}
},
{
component: 'KNavItem',
props: {
title: '快速开始',
description: '通过一个例子快速了解 OpenMCP 的基本概念',
icon: 'quick-fill',
link: '/plugin-tutorial/quick-start/'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP 使用手册',
description: 'OpenMCP Client 的基本使用',
icon: 'shiyongshouce',
link: '/plugin-tutorial/usage/connect-mcp'
}
},
{
component: 'KNavItem',
props: {
title: 'MCP 服务器开发案例',
description: '使用不同语言开发的不同模式的 MCP 服务器',
icon: 'yibangonggongyusuan',
link: '/plugin-tutorial/examples/mcp-examples'
}
},
{
component: 'KNavItem',
props: {
title: 'FAQ',
description: '为您答疑解惑,排忧解难',
icon: 'yijianchuli',
link: '/plugin-tutorial/faq/help'
}
},
]
},
{ text: 'SDK', link: '/sdk-tutorial' },
{
text: '更多',
items: [
{
component: 'KNavItem',
props: {
title: '更新日志',
description: '查看项目的更新历史记录',
icon: 'a-yusuan2',
link: '/preview/changelog'
}
},
{
component: 'KNavItem',
props: {
title: '参与 OpenMCP',
description: '了解如何参与 OpenMCP 项目的开发和维护',
icon: 'shujuzhongxin',
link: '/preview/join'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP 贡献者列表',
description: '关于参与 OpenMCP 的贡献者们',
icon: 'heike',
link: '/preview/contributors'
}
},
{
component: 'KNavItem',
props: {
title: '资源频道',
description: '获取项目相关的资源和信息',
icon: 'xinxiang',
link: '/preview/channel'
}
}
]
},
],
sidebar: {
'/plugin-tutorial/': [
{
text: '简介',
items: [
{ text: 'OpenMCP 概述', link: '/plugin-tutorial/index' },
{ text: '什么是 MCP', link: '/plugin-tutorial/what-is-mcp' },
{ text: 'MCP 基础概念', link: '/plugin-tutorial/concept' }
]
},
{
text: '快速开始',
items: [
{ text: '快速开始', link: '/plugin-tutorial/quick-start' },
{ text: '安装 OpenMCP', link: '/plugin-tutorial/quick-start/acquire-openmcp' },
{ text: '你的第一个 MCP', link: '/plugin-tutorial/quick-start/first-mcp' },
{ text: '快速调试 MCP', link: '/plugin-tutorial/quick-start/quick-debug' },
{ text: '扔进大模型里面测测好坏!', link: '/plugin-tutorial/quick-start/put-into-llm' },
]
},
{
text: "OpenMCP 使用手册",
items: [
{ text: 'UI 配色', link: '/plugin-tutorial/usage/ui-color' },
{ text: '连接 mcp 服务器', link: '/plugin-tutorial/usage/connect-mcp' },
{ text: '调试 tools, resources 和 prompts', link: '/plugin-tutorial/usage/debug' },
{ text: '连接大模型', link: '/plugin-tutorial/usage/connect-llm' },
{ text: '用大模型测试您的 mcp', link: '/plugin-tutorial/usage/test-with-llm' },
{ text: '连接多个 MCP 服务器', link: '/plugin-tutorial/usage/multi-server' },
{ text: '分发您的实验结果', link: '/plugin-tutorial/usage/distribute-result' },
{ text: 'SSE 在线部署的鉴权器实现', link: '/plugin-tutorial/usage/sse-oauth2' },
]
},
{
text: "MCP 服务器开发案例",
items: [
{ text: 'MCP 服务器开发案例', link: '/plugin-tutorial/examples/mcp-examples' },
{ text: '例子 1. python 实现天气信息 mcp 服务器 (STDIO)', link: '/plugin-tutorial/examples/python-simple-stdio' },
{ text: '例子 2. go 实现 neo4j 的只读 mcp 服务器 (SSE)', link: '/plugin-tutorial/examples/go-neo4j-sse' },
{ text: '例子 3. java 实现文档数据库的只读 mcp (HTTP)', link: '/plugin-tutorial/examples/java-es-http' },
{ text: '例子 4. typescript 实现基于 crawl4ai 的超级网页爬虫 mcp (STDIO)', link: '/plugin-tutorial/examples/typescript-crawl4ai-stdio' },
{ text: '例子 5. python 实现进行通用表单填充 的 mcp (STDIO)', link: '/plugin-tutorial/examples/python-form-stdio' },
{ text: '例子 6. python 实现基于 blender 的 mcp (STDIO)', link: '/plugin-tutorial/examples/python-blender-stdio' },
{ text: '例子 7. python 实现 cadence EDA 的 mcp (STDIO)', link: '/plugin-tutorial/examples/python-cadence-stdio' },
]
},
{
text: 'FAQ',
items: [
{ text: '帮助', link: '/plugin-tutorial/faq/help' },
]
}
],
'/sdk-tutorial/': [
{
text: '简介',
items: [
{ text: 'openmcp-sdk.js', link: '/sdk-tutorial/' },
]
},
{
text: '基本使用',
items: [
{ text: '最简单的对话', link: '/sdk-tutorial/usage/greet' },
{ text: '任务循环', link: '/sdk-tutorial/usage/task-loop' },
{ text: '多服务器连接', link: '/sdk-tutorial/usage/multi-server' },
]
}
]
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/LSTM-Kirigaya/openmcp-client' },
{ icon: customIcons.share, link: 'https://kirigaya.cn/home' },
],
footer: {
message: '缩短LLM到Agent的最后一公里',
copyright: 'OpenMCP All rights reserved'
},
search: {
provider: 'local'
},

View File

@ -58,7 +58,7 @@ interface Contributor {
export const contributors = [
{
name: 'LSTM-Kirigaya (锦恢)',
name: '锦恢',
nameAliases: ['LSTM-Kirigaya', 'Kirigaya'],
mapByEmailAliases: ['1193466151@qq.com'],
links: [{ type: '', link: 'https://www.zhihu.com/people/can-meng-zhong-de-che-xian' }]
@ -68,7 +68,7 @@ export const contributors = [
nameAliases: ['li1553770945'],
avatar: 'https://avatars.githubusercontent.com/u/55867654?v=4',
mapByEmailAliases: ['1553770945@qq.com'],
links: [{ type: '', link: 'https://peacesheep.xyz/home' }]
links: [{ type: '', link: 'https://peacesheep.cn/home' }]
},
{
name: '星弧梦影',

View File

@ -1,179 +0,0 @@
export default {
nav: [
{ text: 'Home', link: '/' },
{
text: 'Tutorials',
items: [
{
component: 'KNavItem',
props: {
title: 'Introduction',
description: 'What you need to know about MCP and OpenMCP...',
icon: 'openmcp',
link: '/plugin-tutorial/'
}
},
{
component: 'KNavItem',
props: {
title: 'Quick Start',
description: 'Understand the basic concept of OpenMCP through an example',
icon: 'quick-fill',
link: '/plugin-tutorial/quick-start/'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP User Guide',
description: 'Basic usage of the OpenMCP Client',
icon: 'shiyongshouce',
link: '/plugin-tutorial/usage/connect-mcp'
}
},
{
component: 'KNavItem',
props: {
title: 'MCP Server Examples',
description: 'Examples of MCP servers developed in various languages and models',
icon: 'yibangonggongyusuan',
link: '/plugin-tutorial/examples/mcp-examples'
}
},
{
component: 'KNavItem',
props: {
title: 'FAQ',
description: 'Answers to your questions and solutions to your problems',
icon: 'yijianchuli',
link: '/plugin-tutorial/faq/help'
}
},
]
},
{ text: 'SDK', link: '/sdk-tutorial/' },
{
text: 'More',
items: [
{
component: 'KNavItem',
props: {
title: 'Changelog',
description: 'View the project update history',
icon: 'a-yusuan2',
link: '/preview/changelog'
}
},
{
component: 'KNavItem',
props: {
title: 'Join OpenMCP',
description: 'Learn how to participate in the development and maintenance of OpenMCP',
icon: 'shujuzhongxin',
link: '/preview/join'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP Contributors',
description: 'About the people who contributed to OpenMCP',
icon: 'heike',
link: '/preview/contributors'
}
},
{
component: 'KNavItem',
props: {
title: 'Resource Channel',
description: 'Access resources and information related to the project',
icon: 'xinxiang',
link: '/preview/channel'
}
}
]
}
],
sidebar: {
'/plugin-tutorial/': [
{
text: 'Overview',
items: [
{ text: 'Introduction to OpenMCP', link: '/plugin-tutorial/index' },
{ text: 'What is MCP?', link: '/plugin-tutorial/what-is-mcp' },
{ text: 'Basic Concepts of MCP', link: '/plugin-tutorial/concept' }
]
},
{
text: 'Quick Start',
items: [
{ text: 'Quick Start', link: '/plugin-tutorial/quick-start' },
{ text: 'Install OpenMCP', link: '/plugin-tutorial/quick-start/acquire-openmcp' },
{ text: 'Your First MCP', link: '/plugin-tutorial/quick-start/first-mcp' },
{ text: 'Quick Debugging of MCP', link: '/plugin-tutorial/quick-start/quick-debug' },
{ text: 'Throw it into an LLM and test it!', link: '/plugin-tutorial/quick-start/put-into-llm' }
]
},
{
text: 'User Guide',
items: [
{ text: 'UI Color Settings', link: '/plugin-tutorial/usage/ui-color' },
{ text: 'Connect to MCP Server', link: '/plugin-tutorial/usage/connect-mcp' },
{ text: 'MCP Basic Debugging', link: '/plugin-tutorial/usage/debug' },
{ text: 'MCP Self-Check Tool', link: '/plugin-tutorial/usage/self-check' },
{ text: 'Connect to LLM', link: '/plugin-tutorial/usage/connect-llm' },
{ text: 'MCP Interaction Testing', link: '/plugin-tutorial/usage/test-with-llm' },
{ text: 'Connect to Multiple MCP Services', link: '/plugin-tutorial/usage/multi-server' },
{ text: 'Distribute Experiment Results', link: '/plugin-tutorial/usage/distribute-result' },
{ text: 'Implement SSE Authenticator', link: '/plugin-tutorial/usage/sse-oauth2' }
]
},
{
text: 'Development Examples',
items: [
{ text: 'MCP Server Development Examples', link: '/plugin-tutorial/examples/mcp-examples' },
// { text: 'Example 1: Weather Info MCP in Python (STDIO)', link: '/plugin-tutorial/examples/python-simple-stdio' },
// { text: 'Example 2: Read-only Neo4j MCP in Go (SSE)', link: '/plugin-tutorial/examples/go-neo4j-sse' },
// { text: 'Example 3: Read-only Document DB MCP in Java (HTTP)', link: '/plugin-tutorial/examples/java-es-http' },
// { text: 'Example 4: Super Web Crawler MCP in TypeScript using crawl4ai (STDIO)', link: '/plugin-tutorial/examples/typescript-crawl4ai-stdio' },
// { text: 'Example 5: Generic Form Filling MCP in Python (STDIO)', link: '/plugin-tutorial/examples/python-form-stdio' },
// { text: 'Example 6: Blender-based MCP in Python (STDIO)', link: '/plugin-tutorial/examples/python-blender-stdio' },
// { text: 'Example 7: Cadence EDA MCP in Python (STDIO)', link: '/plugin-tutorial/examples/python-cadence-stdio' }
]
},
{
text: 'FAQ',
items: [
{ text: 'Help', link: '/plugin-tutorial/faq/help' }
]
}
],
'/sdk-tutorial/': [
{
text: 'Introduction',
items: [
{ text: 'openmcp-sdk', link: '/sdk-tutorial/' },
{ text: 'Installation', link: '/sdk-tutorial/install' },
]
},
{
text: 'Basic Usage',
items: [
{ text: 'Simple Chat', link: '/sdk-tutorial/usage/basic' },
{ text: 'Multi-turn Conversation', link: '/sdk-tutorial/usage/send-multi-message' },
{ text: 'Setting Parameters', link: '/sdk-tutorial/usage/setting' },
]
},
{
text: 'MCP',
items: [
{ text: 'Quick Deployment', link: '/sdk-tutorial/usage/fast-deploy' },
{ text: 'Task Loop Control', link: '/sdk-tutorial/usage/task-loop' },
{ text: 'Connect Multiple MCP Servers', link: '/sdk-tutorial/usage/multi-server' },
{ text: 'Human-in-the-Loop (HIL)', link: '/sdk-tutorial/usage/hil' },
]
}
]
}
}

View File

@ -1,178 +0,0 @@
export default {
nav: [
{ text: 'ホーム', link: '/ja/' },
{
text: 'チュートリアル',
items: [
{
component: 'KNavItem',
props: {
title: '概要',
description: 'MCPとOpenMCPについて知っておくべきこと...',
icon: 'openmcp',
link: '/ja/plugin-tutorial/'
}
},
{
component: 'KNavItem',
props: {
title: 'クイックスタート',
description: '例を通してOpenMCPの基本概念を素早く理解しましょう',
icon: 'quick-fill',
link: '/ja/plugin-tutorial/quick-start/'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCPユーザーガイド',
description: 'OpenMCPクライアントの基本的な使い方',
icon: 'shiyongshouce',
link: '/ja/plugin-tutorial/usage/connect-mcp'
}
},
{
component: 'KNavItem',
props: {
title: 'MCPサーバー開発例',
description: 'さまざまな言語と方式で開発されたMCPサーバーの例',
icon: 'yibangonggongyusuan',
link: '/ja/plugin-tutorial/examples/mcp-examples'
}
},
{
component: 'KNavItem',
props: {
title: 'FAQよくある質問',
description: '質問への回答と問題の解決策をご提供します',
icon: 'yijianchuli',
link: '/ja/plugin-tutorial/faq/help'
}
},
]
},
{ text: 'SDK', link: '/ja/sdk-tutorial/' },
{
text: 'もっと見る',
items: [
{
component: 'KNavItem',
props: {
title: '更新履歴',
description: 'プロジェクトの更新履歴を見る',
icon: 'a-yusuan2',
link: '/ja/preview/changelog'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP に参加',
description: 'OpenMCP プロジェクトの開発と保守への参加方法を知る',
icon: 'shujuzhongxin',
link: '/ja/preview/join'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP 貢献者リスト',
description: 'OpenMCP に貢献したメンバーについて',
icon: 'heike',
link: '/ja/preview/contributors'
}
},
{
component: 'KNavItem',
props: {
title: 'リソースチャンネル',
description: 'プロジェクトに関連するリソースや情報を取得する',
icon: 'xinxiang',
link: '/ja/preview/channel'
}
}
]
}
],
sidebar: {
'/ja/plugin-tutorial/': [
{
text: '概要',
items: [
{ text: 'OpenMCP の概要', link: '/ja/plugin-tutorial/index' },
{ text: 'MCP とは?', link: '/ja/plugin-tutorial/what-is-mcp' },
{ text: 'MCP の基本概念', link: '/ja/plugin-tutorial/concept' }
]
},
{
text: 'クイックスタート',
items: [
{ text: 'クイックスタート', link: '/ja/plugin-tutorial/quick-start' },
{ text: 'OpenMCP のインストール', link: '/ja/plugin-tutorial/quick-start/acquire-openmcp' },
{ text: '最初の MCP', link: '/ja/plugin-tutorial/quick-start/first-mcp' },
{ text: 'MCP のクイックデバッグ', link: '/ja/plugin-tutorial/quick-start/quick-debug' },
{ text: '大規模言語モデルで試してみよう!', link: '/ja/plugin-tutorial/quick-start/put-into-llm' }
]
},
{
text: '使用ガイド',
items: [
{ text: 'UI カラー設定', link: '/ja/plugin-tutorial/usage/ui-color' },
{ text: 'MCP サーバーへの接続', link: '/ja/plugin-tutorial/usage/connect-mcp' },
{ text: 'MCP 基本デバッグ', link: '/ja/plugin-tutorial/usage/debug' },
{ text: 'MCP 自己診断ツール', link: '/ja/plugin-tutorial/usage/self-check' },
{ text: '大規模言語モデルへの接続', link: '/ja/plugin-tutorial/usage/connect-llm' },
{ text: 'MCP 対話テスト', link: '/ja/plugin-tutorial/usage/test-with-llm' },
{ text: '複数 MCP サーバーの接続', link: '/ja/plugin-tutorial/usage/multi-server' },
{ text: '実験結果の配布', link: '/ja/plugin-tutorial/usage/distribute-result' },
{ text: 'SSE 認証の実装', link: '/ja/plugin-tutorial/usage/sse-oauth2' }
]
},
{
text: '開発事例',
items: [
{ text: 'MCP サーバー開発事例', link: '/ja/plugin-tutorial/examples/mcp-examples' },
// { text: '例 1. Python による天気情報 MCP サーバー (STDIO)', link: '/ja/plugin-tutorial/examples/python-simple-stdio' },
// { text: '例 2. Go による neo4j 読み取り専用 MCP サーバー (SSE)', link: '/ja/plugin-tutorial/examples/go-neo4j-sse' },
// { text: '例 3. Java によるドキュメントデータベース MCP (HTTP)', link: '/ja/plugin-tutorial/examples/java-es-http' },
// { text: '例 4. TypeScript による crawl4ai ベースのスーパーウェブクローラー MCP (STDIO)', link: '/ja/plugin-tutorial/examples/typescript-crawl4ai-stdio' },
// { text: '例 5. Python による汎用フォーム入力 MCP (STDIO)', link: '/ja/plugin-tutorial/examples/python-form-stdio' },
// { text: '例 6. Python による Blender ベース MCP (STDIO)', link: '/ja/plugin-tutorial/examples/python-blender-stdio' },
// { text: '例 7. Python による Cadence EDA MCP (STDIO)', link: '/ja/plugin-tutorial/examples/python-cadence-stdio' }
]
},
{
text: 'よくある質問',
items: [
{ text: 'ヘルプ', link: '/ja/plugin-tutorial/faq/help' }
]
}
],
'/ja/sdk-tutorial/': [
{
text: 'はじめに',
items: [
{ text: 'openmcp-sdk', link: '/ja/sdk-tutorial/' },
{ text: 'インストール', link: '/ja/sdk-tutorial/install' },
]
},
{
text: '基本操作',
items: [
{ text: '簡単な会話', link: '/ja/sdk-tutorial/usage/basic' },
{ text: 'マルチターン会話', link: '/ja/sdk-tutorial/usage/send-multi-message' },
{ text: 'パラメータ設定', link: '/ja/sdk-tutorial/usage/setting' },
]
},
{
text: 'MCP',
items: [
{ text: 'クイックデプロイ', link: '/ja/sdk-tutorial/usage/fast-deploy' },
{ text: 'タスクループ制御', link: '/ja/sdk-tutorial/usage/task-loop' },
{ text: '複数MCPサーバー接続', link: '/ja/sdk-tutorial/usage/multi-server' },
{ text: 'ヒューマン・イン・ザ・ループ (HIL)', link: '/ja/sdk-tutorial/usage/hil' },
]
}
]
}
}

View File

@ -1,178 +0,0 @@
export default {
nav: [
{ text: '首页', link: '/zh/' },
{
text: '教程',
items: [
{
component: 'KNavItem',
props: {
title: '简介',
description: '关于 mcp 和 openmcp阁下需要知道的 ...',
icon: 'openmcp',
link: '/zh/plugin-tutorial/'
}
},
{
component: 'KNavItem',
props: {
title: '快速开始',
description: '通过一个例子快速了解 OpenMCP 的基本概念',
icon: 'quick-fill',
link: '/zh/plugin-tutorial/quick-start/'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP 使用手册',
description: 'OpenMCP Client 的基本使用',
icon: 'shiyongshouce',
link: '/zh/plugin-tutorial/usage/connect-mcp'
}
},
{
component: 'KNavItem',
props: {
title: 'MCP 服务器开发案例',
description: '使用不同语言开发的不同模式的 MCP 服务器',
icon: 'yibangonggongyusuan',
link: '/zh/plugin-tutorial/examples/mcp-examples'
}
},
{
component: 'KNavItem',
props: {
title: 'FAQ',
description: '为您答疑解惑,排忧解难',
icon: 'yijianchuli',
link: '/zh/plugin-tutorial/faq/help'
}
},
]
},
{ text: 'SDK', link: '/zh/sdk-tutorial/' },
{
text: '更多',
items: [
{
component: 'KNavItem',
props: {
title: '更新日志',
description: '查看项目的更新历史记录',
icon: 'a-yusuan2',
link: '/zh/preview/changelog'
}
},
{
component: 'KNavItem',
props: {
title: '参与 OpenMCP',
description: '了解如何参与 OpenMCP 项目的开发和维护',
icon: 'shujuzhongxin',
link: '/zh/preview/join'
}
},
{
component: 'KNavItem',
props: {
title: 'OpenMCP 贡献者列表',
description: '关于参与 OpenMCP 的贡献者们',
icon: 'heike',
link: '/zh/preview/contributors'
}
},
{
component: 'KNavItem',
props: {
title: '资源频道',
description: '获取项目相关的资源和信息',
icon: 'xinxiang',
link: '/zh/preview/channel'
}
}
]
},
],
sidebar: {
'/zh/plugin-tutorial/': [
{
text: '简介',
items: [
{ text: 'OpenMCP 概述', link: '/zh/plugin-tutorial/index' },
{ text: '什么是 MCP', link: '/zh/plugin-tutorial/what-is-mcp' },
{ text: 'MCP 基础概念', link: '/zh/plugin-tutorial/concept' },
]
},
{
text: '快速开始',
items: [
{ text: '快速开始', link: '/zh/plugin-tutorial/quick-start' },
{ text: '安装 OpenMCP', link: '/zh/plugin-tutorial/quick-start/acquire-openmcp' },
{ text: '你的第一个 MCP', link: '/zh/plugin-tutorial/quick-start/first-mcp' },
{ text: '快速调试 MCP', link: '/zh/plugin-tutorial/quick-start/quick-debug' },
{ text: '扔进大模型里面测测好坏!', link: '/zh/plugin-tutorial/quick-start/put-into-llm' },
]
},
{
text: '使用手册',
items: [
{ text: 'UI 配色', link: '/zh/plugin-tutorial/usage/ui-color' },
{ text: '连接 MCP 服务器', link: '/zh/plugin-tutorial/usage/connect-mcp' },
{ text: 'MCP 基础调试', link: '/zh/plugin-tutorial/usage/debug' },
{ text: 'MCP 工具自检程序', link: '/zh/plugin-tutorial/usage/self-check' },
{ text: '连接大模型', link: '/zh/plugin-tutorial/usage/connect-llm' },
{ text: 'MCP 交互测试', link: '/zh/plugin-tutorial/usage/test-with-llm' },
{ text: '连接多个 MCP 服务', link: '/zh/plugin-tutorial/usage/multi-server' },
{ text: '分发实验结果', link: '/zh/plugin-tutorial/usage/distribute-result' },
{ text: 'SSE 鉴权器实现', link: '/zh/plugin-tutorial/usage/sse-oauth2' },
]
},
{
text: '开发案例',
items: [
{ text: 'MCP 服务器开发案例', link: '/zh/plugin-tutorial/examples/mcp-examples' },
// { text: '例子 1. python 实现天气信息 mcp 服务器 (STDIO)', link: '/zh/plugin-tutorial/examples/python-simple-stdio' },
// { text: '例子 2. go 实现 neo4j 的只读 mcp 服务器 (SSE)', link: '/zh/plugin-tutorial/examples/go-neo4j-sse' },
// { text: '例子 3. java 实现文档数据库的只读 mcp (HTTP)', link: '/zh/plugin-tutorial/examples/java-es-http' },
// { text: '例子 4. typescript 实现基于 crawl4ai 的超级网页爬虫 mcp (STDIO)', link: '/zh/plugin-tutorial/examples/typescript-crawl4ai-stdio' },
// { text: '例子 5. python 实现进行通用表单填充 的 mcp (STDIO)', link: '/zh/plugin-tutorial/examples/python-form-stdio' },
// { text: '例子 6. python 实现基于 blender 的 mcp (STDIO)', link: '/zh/plugin-tutorial/examples/python-blender-stdio' },
// { text: '例子 7. python 实现 cadence EDA 的 mcp (STDIO)', link: '/zh/plugin-tutorial/examples/python-cadence-stdio' },
]
},
{
text: 'FAQ',
items: [
{ text: '帮助', link: '/zh/plugin-tutorial/faq/help' },
]
}
],
'/zh/sdk-tutorial/': [
{
text: '简介',
items: [
{ text: 'openmcpsdk', link: '/zh/sdk-tutorial/' },
{ text: '安装', link: '/zh/sdk-tutorial/install' },
]
},
{
text: '基本使用',
items: [
{ text: '最简单的对话', link: '/zh/sdk-tutorial/usage/basic' },
{ text: '多轮对话', link: '/zh/sdk-tutorial/usage/send-multi-message' },
{ text: '设置对话参数', link: '/zh/sdk-tutorial/usage/setting' },
]
},
{
text: 'MCP',
items: [
{ text: '极速部署', link: '/zh/sdk-tutorial/usage/fast-deploy' },
{ text: '任务循环的控制', link: '/zh/sdk-tutorial/usage/task-loop' },
{ text: '连接多个 MCP 服务器', link: '/zh/sdk-tutorial/usage/multi-server' },
{ text: '人机交互', link: '/zh/sdk-tutorial/usage/hil' },
]
}
]
}
}

Binary file not shown.

View File

@ -3,15 +3,6 @@
<template #home-hero-image>
<HeroImage />
</template>
<template #doc-before>
</template>
<template #doc-after>
<Comments />
</template>
</DefaultTheme.Layout>
<ClientOnly>
<ScrollBar v-if="mounted" />
@ -19,7 +10,7 @@
</template>
<script setup lang="ts">
import { useData, useRouter, inBrowser } from 'vitepress';
import { useData, useRouter } from 'vitepress';
import DefaultTheme from 'vitepress/theme';
import { nextTick, onMounted, provide, ref } from 'vue';
import mediumZoom from "medium-zoom";
@ -30,22 +21,13 @@ import HeroImage from './components/home/HeroImage.vue';
import { gsap } from "gsap/dist/gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import { watchEffect } from 'vue';
import Comments from './components/Comments/index.vue';
const data = useData();
const router = useRouter();
const data = useData()
const router = useRouter()
const enableTransitions = () =>
'startViewTransition' in document &&
window.matchMedia('(prefers-reduced-motion: no-preference)').matches;
// cookies
watchEffect(() => {
if (inBrowser) {
document.cookie = `nf_lang=${data.lang.value}; expires=Mon, 1 Jan 2030 00:00:00 UTC; path=/`;
}
})
const isDark = data.isDark;
const mounted = ref(false);
@ -101,15 +83,8 @@ const handleRouteChangeComplete = async (to: string) => {
router.onBeforeRouteChange = handleRouteChangeStart;
router.onAfterRouteChange = handleRouteChangeComplete;
const allowHomeAnimationRoutes = [
'/openmcp/',
'/openmcp/zh/',
'/openmcp/en/',
'/openmcp/ja/',
];
function makeHomeAnimation() {
if (!allowHomeAnimationRoutes.includes(router.route.path)) {
if (router.route.path !== '/openmcp/') {
return;
}
@ -136,12 +111,11 @@ function makeHomeAnimation() {
const elements = [
{ selector: "#home-0", trigger: '#home-0', start: "top 65%", end: "top 65%" },
{ selector: ".bilibili-player-container", trigger: '#home-0', start: "top 65%", end: "top 65%" },
{ selector: "#home-1", trigger: '#home-1', start: "top 65%", end: "top 65%" },
{ selector: ".k-tabs", trigger: '#home-1', start: "top 65%", end: "top 65%" },
{ selector: "#home-2", trigger: '#home-2', start: "top 65%", end: "top 65%" },
{ selector: ".el-collapse", trigger: '#home-2', start: "top 65%", end: "top 65%" },
{ selector: ".bilibili-player-container", start: "top 65%", end: "top 65%" },
{ selector: "#openmcp-为谁准备", trigger: '#openmcp-为谁准备', start: "top 65%", end: "top 65%" },
{ selector: ".k-tabs", trigger: '#openmcp-为谁准备', start: "top 65%", end: "top 65%" },
{ selector: "#问题解答-faq", trigger: '#问题解答-faq', start: "top 65%", end: "top 65%" },
{ selector: ".el-collapse", trigger: '#问题解答-faq', start: "top 65%", end: "top 65%" },
];
elements.forEach(element => {
@ -198,4 +172,5 @@ body::-webkit-scrollbar {
.medium-zoom-image--opened {
z-index: 999;
}
</style>

View File

@ -1,38 +0,0 @@
<script setup lang="ts">
import { useData } from 'vitepress'
const { title, lang } = useData()
</script>
<template>
<div :key="title" class="giscus comment-block">
<component
:is="'script'"
src="https://giscus.app/client.js"
data-repo="LSTM-Kirigaya/openmcp-document"
data-repo-id="R_kgDOOuuE1g"
data-category="General"
data-category-id="DIC_kwDOOuuE1s4Crh0z"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
:data-lang="lang"
crossorigin="anonymous"
async
/>
</div>
</template>
<style>
.comment-block {
margin-top: 100px;
}
.comment-block iframe {
box-shadow: none !important;
}
</style>

View File

@ -2,10 +2,10 @@
<VPTeamPage>
<VPTeamPageTitle>
<template #title>
{{ messages[lang].title }}
OpenMCP 贡献者列表
</template>
<template #lead>
{{ messages[lang].lead }}
OpenMCP 是一个非盈利的开源项目它由对编程和AI技术热爱的开发者共同开发我们欢迎任何有兴趣参与的开发者加入我们的项目中一起努力提高AI技术的应用水平
</template>
</VPTeamPageTitle>
<VPTeamMembers :members />
@ -16,27 +16,6 @@
import { computed, PropType } from 'vue';
import { VPTeamPage, VPTeamPageTitle, VPTeamMembers } from 'vitepress/theme';
import { customIcons } from '../../hook/icons';
import { useData } from 'vitepress'
const { lang } = useData();
console.log(lang.value);
const messages = {
zh: {
title: 'OpenMCP 贡献者列表',
lead: 'OpenMCP 是一个非盈利的开源项目它由对编程和AI技术热爱的开发者共同开发。我们欢迎任何有兴趣参与的开发者加入我们的项目中一起努力提高AI技术的应用水平。'
},
en: {
title: 'OpenMCP Contributors',
lead: 'OpenMCP is a non-profit open source project developed by developers passionate about programming and AI technology. We welcome any interested developers to join our project and work together to improve the application of AI technology.'
},
ja: {
title: 'OpenMCP コントリビューター一覧',
lead: 'OpenMCPは、プログラミングとAI技術を愛する開発者によって共同開発された非営利のオープンソースプロジェクトです。興味のある開発者の参加を歓迎し、AI技術の応用向上に一緒に取り組みましょう。'
}
}
interface Contributor {
name: string;

View File

@ -1,11 +1,9 @@
<template>
<div class="k-tabs">
<div class="k-tabs" :style="panelStyle">
<div class="k-tabs-tags">
<div class="k-tabs-tag-item" v-for="pane of tabsContainer.paneInfos" :key="pane.id"
:ref="el => tabsContainer.getPanes(el, pane.id)" @click="tabsContainer.switchLabel(pane.id)" :class="{
'active-tab': tabsContainer.lastPaneId === pane.id,
'prev-tab': pane.id === prevActiveIndex
}">
:ref="el => tabsContainer.getPanes(el, pane.id)" @click="tabsContainer.switchLabel(pane.id)"
:class="{ 'active-tab': tabsContainer.lastPaneId === pane.id }">
<span :class="pane.labelClass"></span>
<span>{{ pane.label }}</span>
</div>
@ -17,8 +15,7 @@
</template>
<script setup lang="ts">
import { reactive, useSlots, nextTick, onMounted, ref } from 'vue';
import gsap from 'gsap';
import { reactive, useSlots, provide, nextTick, computed, onMounted } from 'vue';
type PaneInfo = {
id: number;
@ -26,96 +23,116 @@ type PaneInfo = {
labelClass: string;
};
interface TabsContainer {
paneInfos: PaneInfo[];
panes: HTMLElement[];
lastPaneId?: number;
activeLabel: string;
panelContainer?: any;
height: string;
getPanes: (el: any, id: string | number) => void;
switchLabel: (id: number) => void;
updateLabels: () => void;
}
const slots = useSlots();
const prevActiveIndex = ref<number | null>(null);
const tabsContainer = reactive({
paneInfos: [] as PaneInfo[],
panes: [] as HTMLElement[],
lastPaneId: 0,
panelContainer: undefined as any,
getPanes(el: any, id: number) {
if (el) this.panes[id] = el;
},
async switchLabel(id: number) {
if (this.lastPaneId === id) return;
const oldId = this.lastPaneId;
prevActiveIndex.value = oldId;
this.lastPaneId = id;
const container = this.panelContainer;
if (!container) return;
let maxChildHeight = 0;
function resizeTab(id: number) {
const container = tabsContainer.panelContainer;
if (container) {
const panels = Array.from(container.children) as HTMLElement[];
const oldPanel = panels[oldId];
const newPanel = panels[id];
// 1. First shrink the old panel to 0.3 scale
if (oldPanel) {
await gsap.to(oldPanel, {
scale: 0.3,
opacity: 0,
duration: 0.3,
ease: "power2.in"
});
const currentPanel = panels[id];
if (currentPanel) {
maxChildHeight = Math.max(maxChildHeight, currentPanel.clientHeight);
tabsContainer.height = maxChildHeight + 'px';
}
}
}
// 2. Hide all other panels
const panelStyle = computed(() => ({
height: tabsContainer.height
}));
const tabsContainer: TabsContainer = reactive({
paneInfos: [],
panes: [],
lastPaneId: 0,
activeLabel: '',
hoverBar: null,
panelContainer: undefined,
height: '0',
getPanes(el: HTMLElement | null, id: string | number) {
if (el) {
this.panes[id] = el;
}
},
switchLabel(id: number) {
if (this.lastPaneId === id) {
return;
}
this.lastPaneId = id;
this.activeLabel = this.paneInfos[id]?.label || '';
const container = tabsContainer.panelContainer;
const panels = Array.from(container.children) as HTMLElement[];
//
panels.forEach((panel, index) => {
if (index !== id) {
gsap.set(panel, {
display: 'none',
opacity: 0,
scale: 1
});
console.log('index', index);
console.log('id', id);
panel.style.transition = 'opacity 0.3s ease';
if (index === id) {
panel.style.display = 'block';
setTimeout(() => {
panel.style.opacity = '1';
}, 150);
} else {
panel.style.opacity = '0';
setTimeout(() => {
panel.style.display = 'none';
}, 300);
}
});
// 3. Show and animate in the new panel
gsap.set(newPanel, {
display: 'block',
opacity: 0,
scale: 1.2
});
gsap.to(newPanel, {
opacity: 1,
scale: 1,
duration: 0.4,
ease: "back.out(1.2)"
nextTick(() => {
resizeTab(id);
});
},
updateLabels() {
this.paneInfos = (slots.default?.() || []).map((vnode, index) => ({
id: index,
label: vnode.props?.label || '',
labelClass: vnode.props?.labelClass || '',
}));
const defaultChildren = slots.default?.() || [];
this.paneInfos = [];
for (const index in defaultChildren) {
const vnode = defaultChildren[index];
this.paneInfos.push({
id: Number(index),
label: vnode.props?.label || '',
labelClass: vnode.props?.labelClass || '',
});
}
if (this.paneInfos.length > 0) {
this.activeLabel = this.paneInfos[0]?.label || '';
nextTick(() => {
resizeTab(0);
});
}
}
});
// Initialize
tabsContainer.updateLabels();
onMounted(() => {
if (tabsContainer.panelContainer) {
const panels = Array.from(tabsContainer.panelContainer.children) as HTMLElement[];
panels.forEach((panel, index) => {
panel.style.position = 'absolute';
panel.style.width = '100%';
if (index !== 0) {
if (index != tabsContainer.lastPaneId) {
panel.style.display = 'none';
} else {
gsap.from(panel, {
scale: 1.2,
opacity: 0,
duration: 0.5
});
panel.style.opacity = '0';
}
});
}
@ -125,78 +142,58 @@ onMounted(() => {
<style scoped>
.k-tabs {
position: relative;
height: fit-content;
}
.k-tabs-tags {
display: flex;
margin-bottom: 20px;
width: 100%;
position: relative;
z-index: 10;
gap: 8px;
}
@media screen and (max-width: 741px) {
.k-tabs-tags {
flex-direction: column;
}
}
.k-tabs-tag-item {
background-color: var(--vp-button-alt-bg);
border-radius: .5em;
padding: 6px 16px;
margin-right: 10px;
padding: 2px 8px;
font-size: 0.8rem;
display: inline-block;
text-decoration: none;
cursor: pointer;
transition: all 0.3s ease;
transform-origin: center;
will-change: transform;
white-space: nowrap;
user-select: none;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.k-tabs-tag-item {
padding: 6px 16px;
font-size: 1rem;
}
}
.k-tabs-tag-item:hover {
background-color: var(--vp-c-brand-2);
}
.k-tabs-tag-item.active-tab {
background-color: var(--vp-c-brand-3);
transform: scale(1.05);
}
html[lang="zh"] .k-tabs-content {
position: relative;
min-height: 500px;
}
html[lang="en"] .k-tabs-content {
position: relative;
min-height: 550px;
}
html[lang="ja"] .k-tabs-content {
position: relative;
min-height: 600px;
}
@media screen and (max-width: 741px) {
html[lang="zh"] .k-tabs-content {
position: relative;
min-height: 600px;
}
html[lang="en"] .k-tabs-content {
position: relative;
min-height: 900px;
}
html[lang="ja"] .k-tabs-content {
position: relative;
min-height: 760px;
@media screen and (max-width: 414px) {
.k-tabs-tags {
}
}
.hover-bar {
background-color: var(--vp-c-brand-3);
border-radius: .9em .9em 0 0;
transition: .35s ease-in-out;
position: absolute;
}
.k-tabs-content>* {
position: absolute;
top: 0;
left: 0;
width: 100%;
will-change: transform, opacity;
backface-visibility: hidden;
transform-origin: center center;
transition: opacity 0.3s ease;
}
</style>

View File

@ -1,24 +1,22 @@
<template>
<div class="wrapper">
<div class="bilibili-player-container" @mouseenter="onHover" @mouseleave="onHoverEnd">
<div class="bilibili-player-container">
<iframe v-if="isPlaying" :src="playerUrl" frameborder="0" allowfullscreen></iframe>
<div v-else class="cover-container" @click="playVideo">
<img :src="props.cover" class="cover-image" ref="coverImage" />
<button class="play-button" ref="playButton">
<img :src="props.cover" class="cover-image" />
<button class="play-button">
<svg viewBox="0 0 24 24" width="48" height="48">
<path fill="currentColor" d="M8 5v14l11-7z" />
</svg>
</button>
<div class="hover-overlay"></div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import gsap from 'gsap'
import { ref } from 'vue'
const props = defineProps({
url: {
@ -33,56 +31,10 @@ const props = defineProps({
const isPlaying = ref(false);
const playerUrl = ref(props.url);
const coverImage = ref(null);
const playButton = ref(null);
function playVideo() {
isPlaying.value = true
}
function onHover() {
if (!isPlaying.value) {
gsap.to(coverImage.value, {
filter: 'brightness(0.7) saturate(1.2)',
duration: 0.3,
ease: 'power2.out'
});
gsap.to(playButton.value, {
scale: 1.15,
duration: 0.3,
ease: 'elastic.out(1, 0.5)'
});
gsap.to('.hover-overlay', {
opacity: 1,
duration: 0.3
});
}
}
function onHoverEnd() {
if (!isPlaying.value) {
gsap.to(coverImage.value, {
filter: 'brightness(1) saturate(1)',
duration: 0.3,
ease: 'power2.out'
});
gsap.to(playButton.value, {
scale: 1,
duration: 0.3,
ease: 'power2.out'
});
gsap.to('.hover-overlay', {
opacity: 0,
duration: 0.3
});
}
}
onMounted(() => {
//
gsap.set(coverImage.value, { filter: 'brightness(1) saturate(1)' });
gsap.set('.hover-overlay', { opacity: 0 });
});
</script>
<style scoped>
@ -99,40 +51,10 @@ onMounted(() => {
min-height: 225px;
width: 52.36vw;
height: 28.26vw;
border: 2px solid var(--vp-c-brand-3);
border-radius: 8px;
aspect-ratio: 16/9;
border-radius: .5em;
overflow: hidden;
transition: box-shadow 0.3s ease, border-color 0.3s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
@media (max-width: 2700px) {
.bilibili-player-container {
width: 88%;
height: 100%;
}
}
@media (max-width: 1200px) {
.bilibili-player-container {
width: 95%;
height: 100%;
}
}
@media screen and (max-width: 741px) {
.bilibili-player-container iframe {
width: 95%;
height: 230px !important;
}
}
.bilibili-player-container:hover {
border-color: var(--vp-c-brand-1);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
border: 3px solid var(--vp-c-brand-2);
}
.cover-container {
@ -146,19 +68,6 @@ onMounted(() => {
width: 100%;
height: 100%;
object-fit: cover;
transition: filter 0.3s ease;
will-change: filter;
}
.hover-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(var(--vp-c-brand-2-rgb), 0.2) 0%, rgba(var(--vp-c-brand-1-rgb), 0.1) 100%);
pointer-events: none;
will-change: opacity;
}
.play-button {
@ -176,24 +85,16 @@ onMounted(() => {
display: flex;
justify-content: center;
align-items: center;
transition: transform 0.3s ease, background-color 0.3s ease;
will-change: transform;
z-index: 2;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
transition: transform 0.2s ease, background-color 0.2s ease;
}
.play-button:hover {
background-color: var(--vp-c-brand-1);
transform: translate(-50%, -50%) scale(1.2);
transform: translate(-50%, -50%) scale(1.1);
background-color: var(--vp-c-brand-2);
}
.play-button svg {
margin-left: 4px;
transition: transform 0.2s ease;
}
.play-button:hover svg {
transform: scale(1.1);
}
iframe {
@ -201,24 +102,4 @@ iframe {
height: 100%;
border: none;
}
/* 响应式调整 */
@media (max-width: 768px) {
.bilibili-player-container {
min-width: 90vw;
min-height: calc(90vw * 9 / 16);
width: 90vw;
height: calc(90vw * 9 / 16);
}
.play-button {
width: 48px;
height: 48px;
}
.play-button svg {
width: 36px;
height: 36px;
}
}
</style>

View File

@ -1,7 +1,6 @@
<template>
<div style="height: fit-content; width: fit-content; position: relative;" ref="container">
<svg class="VPImage image-src" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg"
ref="svgElement">
<svg class="VPImage image-src" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg" ref="svgElement">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
@ -59,11 +58,6 @@
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<!-- 新增描边渐变色定义 -->
<linearGradient id="strokeGradient" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#A48BF7" />
<stop offset="80%" stop-color="#F7F6FD" />
</linearGradient>
</defs>
<g transform="translate(6 2)">
<g>
@ -92,29 +86,68 @@
</svg>
</div>
</template>
<script setup lang="ts">
<script setup>
import { onMounted, ref } from 'vue'
import { gsap } from 'gsap'
const container = ref<any>(null);
const svgElement = ref<any>(null);
const container = ref(null)
const svgElement = ref(null)
onMounted(() => {
const paths = svgElement.value.querySelectorAll('path');
const paths = svgElement.value.querySelectorAll('path')
// SVG
//
gsap.set(paths, {
strokeDasharray: (_, target) => {
strokeDasharray: (i, target) => {
const length = target.getTotalLength()
target.style.strokeDasharray = length
return length
},
strokeDashoffset: (_, target) => target.getTotalLength(),
stroke: 'url(#strokeGradient)', // 使
strokeWidth: 3.5,
strokeDashoffset: (i, target) => target.getTotalLength(),
stroke: 'var(--vp-c-brand-2)',
strokeWidth: 3,
fillOpacity: 0
})
// 线
const master = gsap.timeline()
// 线
const drawTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" }
})
//
paths.forEach(path => {
drawTimeline.to(path, {
strokeDashoffset: 0,
}, "<+=0.3")
})
// 线
const reverseTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" }
})
//
paths.forEach(path => {
reverseTimeline.to(path, {
fillOpacity: 1,
strokeDashoffset: (i, target) => target.getTotalLength()
}, "<")
})
// 线
const wiggleTimeline = gsap.timeline({
repeat: -1,
yoyo: true,
defaults: {
duration: 2,
ease: "sine.inOut"
}
})
//
const wiggleElements = [
{
@ -133,45 +166,7 @@ onMounted(() => {
el: svgElement.value.querySelector('[transform="translate(388 129)"]'),
x: "+=9", y: "+=4", rotation: "-=2"
}
];
// 线
const master = gsap.timeline();
// 线
const drawTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" }
});
// OpenMCP
paths.forEach((path: gsap.TweenTarget) => {
drawTimeline.to(path, {
strokeDashoffset: 0,
}, "<+=0.3");
});
// 线
const reverseTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" }
});
//
paths.forEach(path => {
reverseTimeline.to(path, {
fillOpacity: 1,
strokeDashoffset: (i, target) => target.getTotalLength()
}, "<")
});
// 线
const wiggleTimeline = gsap.timeline({
repeat: -1,
yoyo: true,
defaults: {
duration: 2,
ease: "sine.inOut"
}
});
]
//
wiggleElements.forEach(item => {
@ -179,26 +174,15 @@ onMounted(() => {
x: item.x,
y: item.y,
rotation: item.rotation,
scale: item.scale,
transformOrigin: "center center"
}, "<")
});
// SVG
gsap.set([
document.querySelector('.VPHero .heading .name.clip'),
document.querySelector('.VPHero .heading .text'),
document.querySelector('.VPHero .tagline'),
document.querySelector('.VPHero .actions'),
...document.querySelectorAll('.VPFeatures .item.grid-3')
], {
opacity: 1,
y: 0,
scale: 1
});
})
//
master.add(drawTimeline)
.add(reverseTimeline, "+=0.3")
.add(wiggleTimeline, "<+=0.2");
.add(reverseTimeline, "+=0.5")
.add(wiggleTimeline) //
})
</script>

View File

@ -59,7 +59,6 @@
background-color: var(--vp-c-brand-3);
}
.VPFeatures .item:hover .box .title,
.VPFeatures .item:hover .box .details {
color: var(--vp-c-white);
}

View File

@ -1,187 +0,0 @@
/* Giscus评论系统主题适配 */
:root {
/* 浅色主题变量 */
--giscus-light-bg: #ffffff;
--giscus-light-text: #22272e;
--giscus-light-border: #e1e4e8;
--giscus-light-btn-bg: #f6f8fa;
--giscus-light-btn-hover: #f3f4f6;
--giscus-light-comment-bg: #f6f8fa;
--giscus-light-link: var(--vp-c-brand-2);
--giscus-light-code-bg: rgba(175, 184, 193, 0.2);
/* 深色主题变量 */
--giscus-dark-bg: #15202b;
--giscus-dark-text: #adbac7;
--giscus-dark-border: #444c56;
--giscus-dark-btn-bg: #373e47;
--giscus-dark-btn-hover: #444c56;
--giscus-dark-comment-bg: #1e2d3b;
--giscus-dark-link: var(--vp-c-brand-1);
--giscus-dark-code-bg: rgba(99, 110, 123, 0.4);
}
/* 基础样式 */
main {
/* 使用您的品牌色重新定义语法高亮 */
--color-prettylights-syntax-comment: var(--vp-c-text-2);
--color-prettylights-syntax-constant: var(--vp-c-brand-1);
--color-prettylights-syntax-entity: var(--vp-c-brand-2);
--color-prettylights-syntax-storage-modifier-import: var(--vp-c-text-1);
--color-prettylights-syntax-entity-tag: #8ddb8c;
--color-prettylights-syntax-keyword: #f47067;
--color-prettylights-syntax-string: #96d0ff;
--color-prettylights-syntax-variable: #f69d50;
--color-prettylights-syntax-brackethighlighter-unmatched: #e5534b;
--color-prettylights-syntax-invalid-illegal-text: var(--vp-c-text-1);
--color-prettylights-syntax-invalid-illegal-bg: #922323;
--color-prettylights-syntax-carriage-return-text: var(--vp-c-text-1);
--color-prettylights-syntax-carriage-return-bg: #ad2e2c;
--color-prettylights-syntax-string-regexp: #8ddb8c;
--color-prettylights-syntax-markup-list: #eac55f;
--color-prettylights-syntax-markup-heading: var(--vp-c-brand-3);
--color-prettylights-syntax-markup-italic: var(--vp-c-text-1);
--color-prettylights-syntax-markup-bold: var(--vp-c-text-1);
--color-prettylights-syntax-markup-deleted-text: #ffd8d3;
--color-prettylights-syntax-markup-deleted-bg: #78191b;
--color-prettylights-syntax-markup-inserted-text: #b4f1b4;
--color-prettylights-syntax-markup-inserted-bg: #1b4721;
--color-prettylights-syntax-markup-changed-text: #ffddb0;
--color-prettylights-syntax-markup-changed-bg: #682d0f;
--color-prettylights-syntax-markup-ignored-text: var(--vp-c-text-2);
--color-prettylights-syntax-markup-ignored-bg: #255ab2;
--color-prettylights-syntax-meta-diff-range: var(--vp-c-brand-2);
/* 按钮样式 */
--color-btn-text: var(--vp-c-text-1);
--color-btn-bg: var(--vp-c-default-soft);
--color-btn-border: var(--vp-c-border);
--color-btn-shadow: 0 0 transparent;
--color-btn-inset-shadow: 0 0 transparent;
--color-btn-hover-bg: var(--vp-c-default-2);
--color-btn-hover-border: var(--vp-c-border);
--color-btn-active-bg: var(--vp-c-default-3);
--color-btn-active-border: var(--vp-c-border);
--color-btn-selected-bg: var(--vp-c-default-3);
/* 主按钮样式 - 使用您的品牌色 */
--color-btn-primary-text: var(--vp-c-white);
--color-btn-primary-bg: var(--vp-c-brand-3);
--color-btn-primary-border: transparent;
--color-btn-primary-shadow: 0 0 transparent;
--color-btn-primary-inset-shadow: 0 0 transparent;
--color-btn-primary-hover-bg: var(--vp-c-brand-2);
--color-btn-primary-hover-border: transparent;
--color-btn-primary-selected-bg: var(--vp-c-brand-3);
--color-btn-primary-selected-shadow: 0 0 transparent;
--color-btn-primary-disabled-text: rgba(255, 255, 255, 0.5);
--color-btn-primary-disabled-bg: rgba(163, 104, 184, 0.6);
--color-btn-primary-disabled-border: transparent;
/* 其他元素 */
--color-fg-default: var(--vp-c-text-1);
--color-fg-muted: var(--vp-c-text-2);
--color-fg-subtle: var(--vp-c-text-3);
--color-canvas-default: var(--vp-c-bg);
--color-canvas-overlay: var(--vp-c-bg-soft);
--color-canvas-inset: var(--vp-c-bg-alt);
--color-canvas-subtle: var(--vp-c-bg-soft);
--color-border-default: var(--vp-c-border);
--color-border-muted: var(--vp-c-divider);
--color-accent-fg: var(--vp-c-brand-1);
--color-accent-emphasis: var(--vp-c-brand-3);
--color-accent-muted: var(--vp-c-brand-soft);
--color-accent-subtle: var(--vp-c-brand-soft);
/* 加载动画 */
--color-homepage-bg: var(--vp-c-bg);
}
/* 浅色主题适配 */
@media (prefers-color-scheme: light) {
main {
--color-canvas-default: var(--giscus-light-bg);
--color-canvas-overlay: var(--giscus-light-comment-bg);
--color-canvas-inset: var(--giscus-light-comment-bg);
--color-canvas-subtle: var(--giscus-light-btn-bg);
--color-fg-default: var(--giscus-light-text);
--color-fg-muted: #57606a;
--color-fg-subtle: #6e7781;
--color-border-default: var(--giscus-light-border);
--color-border-muted: #d0d7de;
--color-btn-bg: var(--giscus-light-btn-bg);
--color-btn-hover-bg: var(--giscus-light-btn-hover);
--color-accent-fg: var(--giscus-light-link);
--color-prettylights-syntax-comment: #6e7781;
}
}
/* 深色主题适配 */
@media (prefers-color-scheme: dark) {
main {
--color-canvas-default: var(--giscus-dark-bg);
--color-canvas-overlay: var(--giscus-dark-comment-bg);
--color-canvas-inset: var(--giscus-dark-comment-bg);
--color-canvas-subtle: var(--giscus-dark-btn-bg);
--color-fg-default: var(--giscus-dark-text);
--color-fg-muted: #768390;
--color-fg-subtle: #545d68;
--color-border-default: var(--giscus-dark-border);
--color-border-muted: #373e47;
--color-btn-bg: var(--giscus-dark-btn-bg);
--color-btn-hover-bg: var(--giscus-dark-btn-hover);
--color-accent-fg: var(--giscus-dark-link);
--color-prettylights-syntax-comment: #768390;
}
}
/* 自定义样式 */
.gsc-reactions-count {
display: none;
}
.gsc-timeline {
flex-direction: column-reverse;
}
.gsc-header {
padding-bottom: 1rem;
}
.gsc-comments>.gsc-header {
order: 1;
}
.gsc-comments>.gsc-comment-box {
margin-bottom: 1rem;
order: 2;
}
.gsc-comments>.gsc-timeline {
order: 3;
}
main .gsc-loading-image {
background-image: url(https://github.githubassets.com/images/mona-loading-dimmed.gif);
}
/* 链接颜色 */
.gsc-comment a {
color: var(--color-accent-fg) !important;
}
/* 代码块背景 */
.gsc-comment markdown-body pre {
background-color: var(--color-canvas-subtle) !important;
}
/* 评论框样式 */
.gsc-comment-box {
border: 1px solid var(--color-border-default) !important;
background-color: var(--color-canvas-default) !important;
}
/* 按钮悬停效果 */
.gsc-reaction-button:hover {
background-color: var(--color-btn-hover-bg) !important;
}

View File

@ -217,12 +217,6 @@ iframe {
transition: border-color 0.3s ease;
}
@media screen and (max-width: 741px) {
iframe {
height: 210px;
width: 100%;
}
}
.VPMenu {
background-color: rgba(255, 255, 255, 0.55) !important;
@ -272,53 +266,7 @@ iframe {
color: white;
}
.VPHero .heading .name.clip {
background: var(--vp-home-hero-name-background);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: var(--vp-home-hero-name-color);
.VPHero .name.clip {
color: var(--vp-c-brand-2) !important;
background-color: var(--vp-c-brand-2) !important;
}
/*
.VPHero .heading .text {
}
.VPHero .tagline {
}
.VPHero .actions {
}
*/
#home-0 {
font-size: 40px;
line-height: 1.1;
}
#home-0 > span {
font-size: 20px;
opacity: 0.5;
line-height: 0.8;
}
#home-1 {
font-size: 40px;
line-height: 1.1;
}
#home-1 > span {
font-size: 20px;
opacity: 0.5;
line-height: 0.8;
}
#home-2 {
font-size: 40px;
line-height: 1.1;
}
#home-2 > span {
font-size: 20px;
opacity: 0.5;
line-height: 0.8;
}

View File

@ -1,95 +0,0 @@
@font-face {
font-family: "iconfont"; /* Project id 4933953 */
src: url('iconfont.woff2?t=1748520354582') format('woff2'),
url('iconfont.woff?t=1748520354582') format('woff'),
url('iconfont.ttf?t=1748520354582') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-quick-fill:before {
content: "\e863";
}
.icon-heike:before {
content: "\e6c5";
}
.icon-bumendongtai:before {
content: "\e61f";
}
.icon-duzhengyishi:before {
content: "\e620";
}
.icon-lianwangzhongxin:before {
content: "\e621";
}
.icon-fenxitongji:before {
content: "\e622";
}
.icon-shujuzhongxin:before {
content: "\e623";
}
.icon-shuju:before {
content: "\e624";
}
.icon-shenji:before {
content: "\e625";
}
.icon-yusuan:before {
content: "\e626";
}
.icon-yibangonggongyusuan:before {
content: "\e627";
}
.icon-xinxiang:before {
content: "\e628";
}
.icon-yujing:before {
content: "\e629";
}
.icon-yijianchuli:before {
content: "\e62a";
}
.icon-zhuanti:before {
content: "\e62b";
}
.icon-a-yusuan2:before {
content: "\e62c";
}
.icon-yujuesuanshencha:before {
content: "\e62d";
}
.icon-zhengcefagui:before {
content: "\e62e";
}
.icon-ziliao:before {
content: "\e62f";
}
.icon-zixuntousu:before {
content: "\e630";
}

Binary file not shown.

View File

@ -1,8 +1,6 @@
// https://vitepress.dev/guide/custom-theme
import { h } from 'vue';
import type { Theme } from 'vitepress';
import { inBrowser } from 'vitepress';
import busuanzi from 'busuanzi.pure.js';
import DefaultTheme from 'vitepress/theme';
import CustomLayout from './Layout.vue';
@ -48,12 +46,5 @@ export default {
app.use(NolebaseGitChangelogPlugin);
app.use(NolebaseInlineLinkPreviewPlugin);
// 添加浏览量统计
if (inBrowser) {
router.onAfterRouteChange = () => {
busuanzi.fetch()
}
}
}
} satisfies Theme

BIN
.vscode/.DS_Store vendored

Binary file not shown.

31
.vscode/openmcp_connection.json vendored Normal file
View File

@ -0,0 +1,31 @@
{
"items": [
[],
[],
[],
[
{
"connectionType": "SSE",
"name": "SSE-1748530644202",
"version": "1.0",
"url": "http://localhost:8000/mcp",
"oauth": ""
}
],
[],
[],
[],
[],
[],
[
{
"connectionType": "SSE",
"name": "SSE-1748531219080",
"version": "1.0",
"url": "http://localhost:8000/sse",
"oauth": ""
}
],
[]
]
}

215
.vscode/tabs.my-browser.json vendored Normal file
View File

@ -0,0 +1,215 @@
{
"clientId": "81b3b1d6-b1d6-53b1d63c156-83b1d63c156a678-6a678e36",
"currentIndex": 0,
"tabs": [
{
"name": "交互测试",
"icon": "icon-robot",
"type": "blank",
"componentIndex": 3,
"storage": {
"activeNames": [
0
],
"messages": [
{
"role": "user",
"content": "使用 ffmpeg 把视频 (0, 65) 到 (1173, 769) 的位置截取出来,视频的格式是 mov我希望导出为 mp4",
"extraInfo": {
"created": 1749111492698,
"state": "success",
"serverName": "deepseek"
}
},
{
"role": "assistant",
"content": "你可以使用 `ffmpeg` 的 `crop` 滤镜来截取视频的指定区域,并将 `.mov` 转换为 `.mp4` 格式。以下是具体的命令:\n\n### 命令解析:\n1. **输入文件**`input.mov`(替换为你的文件名)\n2. **裁剪参数**\n - `crop=w:h:x:y`:从坐标 `(x,y)` 开始,截取宽度 `w`、高度 `h` 的区域。\n - 你的需求是从 `(0, 65)` 到 `(1173, 769)`,因此:\n - 宽度 `w = 1173 - 0 = 1173`\n - 高度 `h = 769 - 65 = 704`\n - 起始坐标 `(x,y) = (0, 65)`\n3. **输出格式**`mp4`(默认使用 H.264 编码)\n\n### 完整命令:\n```bash\nffmpeg -i input.mov -filter:v \"crop=1173:704:0:65\" -c:a copy output.mp4\n```\n\n### 参数说明:\n- `-i input.mov`:指定输入文件。\n- `-filter:v \"crop=1173:704:0:65\"`:视频裁剪滤镜。\n- `-c:a copy`:直接复制音频流(无需重新编码,节省时间)。\n- `output.mp4`:输出文件名。\n\n### 其他选项:\n- 如果需要控制视频质量,可以添加 `-crf` 参数(默认 23值越小质量越高\n ```bash\n ffmpeg -i input.mov -filter:v \"crop=1173:704:0:65\" -crf 18 -c:a copy output.mp4\n ```\n- 如果需要硬件加速(如 NVIDIA GPU可以添加 `-hwaccel cuda` 等参数。\n\n### 注意:\n1. 确保 `ffmpeg` 已安装并添加到系统路径。\n2. 如果视频有旋转/缩放等元数据,可能需要先处理(如用 `-vf \"transpose=1\"` 旋转)。\n\n运行命令后`output.mp4` 就是你需要的裁剪后视频。",
"extraInfo": {
"created": 1749111520497,
"state": "success",
"serverName": "deepseek",
"usage": {
"prompt_tokens": 42,
"completion_tokens": 487,
"total_tokens": 529,
"prompt_tokens_details": {
"cached_tokens": 0
},
"prompt_cache_hit_tokens": 0,
"prompt_cache_miss_tokens": 42
}
}
}
],
"settings": {
"modelIndex": 0,
"enableTools": [
{
"name": "k_navigate",
"description": "Navigate to a URL",
"inputSchema": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "URL to navigate to"
},
"launchOptions": {
"type": "object",
"description": "PuppeteerJS LaunchOptions. Default null. If changed and not null, browser restarts. Example: { headless: true, args: ['--no-sandbox'] }"
},
"allowDangerous": {
"type": "boolean",
"description": "Allow dangerous LaunchOptions that reduce security. When false, dangerous args like --no-sandbox will throw errors. Default false."
}
},
"required": [
"url"
]
},
"enabled": false
},
{
"name": "k_screenshot",
"description": "Take a screenshot of the current page or a specific element",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name for the screenshot"
},
"selector": {
"type": "string",
"description": "CSS selector for element to screenshot"
},
"width": {
"type": "number",
"description": "Width in pixels (default: 800)"
},
"height": {
"type": "number",
"description": "Height in pixels (default: 600)"
}
},
"required": [
"name"
]
},
"enabled": false
},
{
"name": "k_click",
"description": "Click an element on the page",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for element to click"
}
},
"required": [
"selector"
]
},
"enabled": false
},
{
"name": "k_fill",
"description": "Fill out an input field",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for input field"
},
"value": {
"type": "string",
"description": "Value to fill"
}
},
"required": [
"selector",
"value"
]
},
"enabled": false
},
{
"name": "k_select",
"description": "Select an element on the page with Select tag",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for element to select"
},
"value": {
"type": "string",
"description": "Value to select"
}
},
"required": [
"selector",
"value"
]
},
"enabled": false
},
{
"name": "k_hover",
"description": "Hover an element on the page",
"inputSchema": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "CSS selector for element to hover"
}
},
"required": [
"selector"
]
},
"enabled": false
},
{
"name": "k_evaluate",
"description": "Execute JavaScript in the browser console",
"inputSchema": {
"type": "object",
"properties": {
"script": {
"type": "string",
"description": "JavaScript code to execute"
}
},
"required": [
"script"
]
},
"enabled": false
},
{
"name": "k_get_full_page_text",
"description": "获取页面所有文本内容",
"inputSchema": {
"type": "object",
"properties": {}
},
"enabled": false
}
],
"enableWebSearch": false,
"temperature": 0.6,
"contextLength": 20,
"systemPrompt": "",
"parallelToolCalls": true
}
}
}
]
}

BIN
images/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

BIN
images/icons/.DS_Store vendored

Binary file not shown.

View File

@ -1,9 +0,0 @@
<svg t="1748332079467" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="1357" width="200" height="200">
<path
d="M490.08 116.288L868.736 928.32a32 32 0 1 0 58.016-27.072L548.064 89.28a32 32 0 1 0-57.984 27.04z"
fill="var(--vp-c-brand-1)" p-id="1358"></path>
<path
d="M550.176 116.288L171.488 928.32a32 32 0 1 1-57.984-27.072L492.16 89.28a32 32 0 0 1 58.016 27.04z"
fill="var(--vp-c-text-1)" p-id="1359"></path>
</svg>

Before

Width:  |  Height:  |  Size: 504 B

View File

@ -1,9 +0,0 @@
<svg t="1748332003112" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="1198" width="200" height="200">
<path
d="M82.784 773.76l409.152 175.36c23.36 10.016 49.824 10.016 73.184 0l409.152-175.36a30.976 30.976 0 0 0-24.384-56.96l-409.152 175.36a30.976 30.976 0 0 1-24.416 0L107.2 716.8a30.976 30.976 0 1 0-24.384 56.96z"
fill="var(--vp-c-brand-1)" p-id="1199"></path>
<path
d="M949.888 469.088a30.976 30.976 0 1 1 24.384 56.928l-409.152 175.36a92.896 92.896 0 0 1-73.184 0l-409.152-175.36a30.976 30.976 0 0 1 24.384-56.96l409.152 175.36a30.976 30.976 0 0 0 24.416 0zM539.008 65.504l4.032 1.408L969.824 245.76a38.016 38.016 0 0 1 0 70.048L543.04 494.624c-9.28 3.904-19.744 3.904-29.024 0L87.232 315.84a38.016 38.016 0 0 1 0-70.08l426.784-178.816c7.968-3.328 16.768-3.808 24.96-1.408zM528.48 128L163.904 280.768l364.608 152.8 364.64-152.8L528.512 128z"
fill="var(--vp-c-text-1)" p-id="1200"></path>
</svg>

Before

Width:  |  Height:  |  Size: 988 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,9 +0,0 @@
<svg t="1748331856103" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="986" width="200" height="200">
<path
d="M786.56 887.744a28.896 28.896 0 0 1 0 57.792H208.544a28.896 28.896 0 0 1 0-57.792zM844.416 64a86.72 86.72 0 0 1 86.72 86.72V699.84a86.72 86.72 0 0 1-86.72 86.72H150.72A86.72 86.72 0 0 1 64 699.84V150.72A86.72 86.72 0 0 1 150.72 64h693.664z m0 57.792H150.72a28.896 28.896 0 0 0-28.928 28.928V699.84c0 15.968 12.96 28.896 28.928 28.896h693.664a28.896 28.896 0 0 0 28.896-28.896V150.72a28.896 28.896 0 0 0-28.896-28.928z"
fill="var(--vp-c-text-1)" p-id="987"></path>
<path
d="M228.352 548.224l166.592-157.376 172.064 160.48 244.768-235.264a28.896 28.896 0 0 0-40.064-41.664L566.4 471.744l-171.712-160.16-206.016 194.592a28.896 28.896 0 1 0 39.68 42.048z"
fill="var(--vp-c-brand-1)" p-id="988"></path>
</svg>

Before

Width:  |  Height:  |  Size: 903 B

View File

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="2545" height="834" viewBox="0 0 2545 834" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="182.5" y1="0" x2="182.5" y2="365">
<stop offset="0.382" stop-color="#A594F6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-363" y="-363" width="365" height="365" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g>
<g>
<g transform="translate(145 58)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)" transform="translate(294 341)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path d="M0 182.5C0 81.708 81.708 0 182.5 0C283.292 0 365 81.708 365 182.5C365 283.292 283.292 365 182.5 365C81.708 365 0 283.292 0 182.5Z" fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 39)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)" transform="translate(401 130)" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 KiB

After

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 KiB

122
index.md
View File

@ -4,12 +4,12 @@ layout: home
hero:
name: "OpenMCP"
text: "MCP Debugger and SDK for Elegant Developers"
tagline: Bridge the last mile from large language models to intelligent agents
text: "面向优雅开发者的 MCP 调试器和 SDK"
tagline: 缩短从大语言模型到智能体的最后一公里
actions:
- theme: brand
text: OpenMCP Plugin
text: OpenMCP 插件
link: ./plugin-tutorial
- theme: alt
text: openmcp-sdk
@ -21,107 +21,95 @@ features:
- icon:
src: /images/icons/vscode.svg
height: 48px
alt: Integrated Debugging Environment
title: Integrated Debugging Environment
details: Combine the inspector with MCP client functions to achieve seamless development and testing
alt: 集成调试环境
title: 集成调试环境
details: 将检查器与 MCP 客户端功能相结合,实现无缝开发和测试
- icon:
src: /images/icons/openmcp-edge.svg
height: 48px
alt: Provide a complete project-level control panel
title: Comprehensive Project Management
details: Provide a complete project-level control panel for efficient MCP project supervision
alt: 提供完整的项目级控制面板
title: 全面的项目管理
details: 提供完整的项目级控制面板,实现高效的 MCP 项目监督
- icon:
src: /images/icons/openmcp-sdk.svg
height: 48px
alt: Provide a complete project-level control panel
title: Complete Deployment Solution
details: Deploy tested agents to your application or server via openmcp-sdk
alt: 提供完整的项目级控制面板
title: 完整的部署方案
details: 将测试完成的 agent 通过 openmcp-sdk 部署到您的应用或者服务器上
---
<br><br>
<h2 id="home-0">
Resolve Issues in Your MCP Agent Development
<br>
<span>Providing Fun and Convenience for Your MCP Agent Development</span>
</h2>
<div class="bilibili-player-container" style="display:flex; width: 100%; justify-content: center;">
<iframe width="90%" height="580" src="https://www.youtube.com/embed/S7igsEhcLiw?si=6sqvbYJxSRoFS26g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div>
<BiliPlayer
url="//player.bilibili.com/player.html?isOutside=true&aid=114445745397200&bvid=BV1zYGozgEHcautoplay=false"
cover="https://picx.zhimg.com/80/v2-8c1f5d99066ed272554146ed8caf7cc3_1440w.png"
/>
<br>
<h2 id="home-1">
Who is OpenMCP for?
<br>
<span>The Development of OpenMCP is for ...</span>
</h2>
## OpenMCP 为谁准备?
<br>
<KTab class="home-tab">
<TwoSideLayout
label="Professional Software Engineers"
label="专业软件工程师"
:texts="[
'Shift testing left integrates development and testing seamlessly with rich features, no third-party tools needed.',
'Easily manage, debug, and test AI agents via the left-hand panel.',
'Monitor LLM tool details and instantly reproduce unsatisfactory results with one click.',
'Track performance metrics per conversation for better cost control.',
'Build AI agent apps effortlessly using MCP servers and system prompts via the management panel.'
]"
image="./images/openmcp.xml.png"
/>
<TwoSideLayout
label="Open - Source Community Enthusiasts"
:texts="[
'Shift-left testing integrates dev and testing without third-party tools, packed with rich features.',
'OpenMCP is fully open-source—use it free or collaborate to build agent innovations.',
'Full technical transparency protects your ideas and tokens from plagiarism risks.',
'Persistent prompt management lets you test and share real MCP server prompts.',
'Every test is Git-versioned for easy sharing and zero-cost replication of MCP projects.'
'测试左移,让你的开发与测试一体化,无需打开第三方软件。提供极其丰富的功能和特性。',
'在左侧面板自由而优雅地管理、调试和测试你的智能体。',
'大模型调用工具的每一个细节一览无余,不满意的调用结果直接一键复现。',
'每一次对话都会显示各项性能指标,方便进行成本管理。',
'系统提示词管理面板,让您轻松用 mcp 服务器和系统提示词构建您的智能体应用。',
]"
image="./images/openmcp.chatbot.png"
/>
<TwoSideLayout
label="AI Research Scientists"
label="开源社区爱好者"
:texts="[
'Shift-left testing integrates development and testing without third-party tools, offering rich features.',
'Convert research into MCP servers with minimal code, linking any LLM for a seamless UI.',
'Auto-track experiments & configs in Git for reproducible, traceable research.',
'OpenMCP accelerates demos, bridging innovation and deployment.'
'测试左移,让你的开发与测试一体化,无需打开第三方软件。提供极其丰富的功能和特性。',
'OpenMCP 完全开源,您不仅可以免费试用此产品,也可以一起加入我们,实现你的关于 Agent 的奇思妙想。',
'完全公开技术细节您不必担心您的创意和token会遭到剽窃。',
'可持久化的系统提示词管理面板,让您可以将实际的 mcp 服务器的系统提示词进行测试,以便于在社区内进行分享。',
'每一次测试的细节都会 100% 跟随 git 进行版本控制,方便你分享你的每一次试验结果,也方便你零成本复现别人的 mcp 项目。'
]"
image="./images/openmcp.resource.png"
image="./images/opensource.png"
/>
<TwoSideLayout
label="AI研发科学家"
:texts="[
'测试左移,让你的开发与测试一体化,无需打开第三方软件。提供极其丰富的功能和特性。',
'只需几行代码,就能快速将您的科研成果做成 mcp 服务器,从而接入任意大模型,以实现用户友好型的交互界面。',
'所有实验数据与配置参数均自动纳入Git版本管理系统确保研究成果可追溯、可复现便于学术交流与论文复现。',
'基于 OpenMCP 快速完成您的 demo缩短创新到落地的距离。',
]"
image="./images/openmcp.chatbot.png"
/>
</KTab>
<br>
<h2 id="home-2">
FAQ
<br>
<span>Waiting for Your Questions</span>
</h2>
## 问题解答 FAQ
<el-collapse>
<el-collapse-item title="What is OpenMCP suitable for?" name="1">
As its name suggests, OpenMCP is an MCP debugger and SDK for developers, committed to reducing the full - chain development cost of AI agents and the mental burden of developers. Our mission is to create MCP tools that can solve real - life problems and save working time through OpenMCP, or help engineers and research scientists deliver demos more quickly and make this vision visible to the public.
<el-collapse-item title="OpenMCP 适合做什么?" name="1">
正如它的名字一样OpenMCP 是一个面向开发者的 MCP 调试器和 SDK致力于降低 AI Agent 的全链路开发成本和开发人员的心智负担。通过 OpenMCP 制作出可以在真实生活场景中解决问题,缩短工作时间的 mcp 工具,或是让工程师与研发科学家更快地交付 demo并将这份愿景让公众看到是我们的任务和使命。
</el-collapse-item>
<el-collapse-item title="Is OpenMCP free?" name="2">
Yes, OpenMCP is completely open - source. You can not only use this product for free but also join us to realize your creative ideas about agents. The task of OpenMCP is to build an ecosystem around MCP. We believe that MCP development will be a highly customized task in the future, so our current focus is not to rush to create an all - purpose agent, but to steadily build the relevant ecosystem and infrastructure.
<el-collapse-item title="OpenMCP 是免费的吗?" name="2">
是的OpenMCP 完全开源,您不仅可以免费使用此产品,也可以一起加入我们,实现你的关于 Agent 的奇思妙想。OpenMCP 的任务是建立起关于 MCP 的生态圈。因为我们认为MCP 的开发在未来一段时间内会是一项高度定制化的工作,所以当前的重点并不是赶紧出做一个看起来什么都能做的 Agent而是步步为营做出相关的生态和基础设施。
</el-collapse-item>
<el-collapse-item title="What is OpenMCP not suitable for?" name="3">
If you try to develop an all - purpose, general AI agent through OpenMCP, you should invest all your money in the research and development of quantum computers instead of visiting this website. Remember, in this era, developing a full - domain general AI agent is likely to be equivalent to telecom fraud.
<el-collapse-item title="OpenMCP 不适合做什么?" name="3">
如果你试图通过 OpenMCP 开发一款什么都能做的,通用的 AI Agent你应该做的是把钱全部投资到量子计算机的研发而不是点开这个网站。记住一句话这个时代做全领域通用AI Agent依概率收敛到电信诈骗。
</el-collapse-item>
<el-collapse-item title="Who is developing OpenMCP?" name="4">
<p>OpenMCP was initially led by LSTM - Kirigaya (Jinhui) for building MCP testing tools related to 3D work. Its main participants include employees from large companies, students majoring in computer - related fields at universities, and some active contributors from the open - source community.</p>
<p>Identity is not important. I'd like to share a quote with you: "Don't tell me if you can do it. Tell me if you like it."</p>
<el-collapse-item title="OpenMCP 都是什么人在开发?" name="4">
<p>OpenMCP 是由 LSTM-Kirigaya(锦恢) 最初主导开发的,用于构建 3D 相关工作的 mcp 测试工具。它的主要参与者都是大厂在职员工,高校计算机相关专业的学生、以及一些开源社区的活跃贡献者。</p>
<p>身份不重要,我非常喜欢的一句话,送给阁下:“不要回答我你会不会,回答我,你喜不喜欢”。</p>
<img src="https://pica.zhimg.com/80/v2-3666e84b2f92bf444a5eb64fb9d08e71_1440w.png" style="max-width: 500px;margin-top:10px;"/>
</el-collapse-item>
<el-collapse-item title="How can I join you or participate in discussions?" name="5">
You can learn how to participate in the maintenance and development of OpenMCP through <a href="https://kirigaya.cn/openmcp/preview/join.html" target="_blank">Participate in OpenMCP</a>. Obtain our contact information through <a href="https://kirigaya.cn/openmcp/preview/channel.html" target="_blank">Resource Channel</a>. Currently, there are three main communities: QQ group: 782833642, <a href="https://discord.com/invite/SKTZRf6NzU" target="_blank">OpenMCP Discord Channel</a>, and <a href="https://www.zhihu.com/ring/host/1911121615279849840" target="_blank">Zhihu Circle [OpenMCP Museum]</a>
<el-collapse-item title="如何加入我们或者参与讨论?" name="5">
您可以通过 <a href="https://kirigaya.cn/openmcp/preview/join.html" target="_blank">参与 OpenMCP</a> 来了解如何参与 OpenMCP 的维护和开发。通过 <a href="https://kirigaya.cn/openmcp/preview/channel.html" target="_blank">资源频道</a> 来获取我们的联系方式。目前主要的社区有三个QQ群782833642 、 <a href="https://discord.com/invite/SKTZRf6NzU" target="_blank">OpenMCP Discord 频道</a> <a href="https://www.zhihu.com/ring/host/1911121615279849840" target="_blank">知乎圈子【OpenMCP 博物馆】</a>
</el-collapse-item>
<el-collapse-item title="How to contact us for cooperation?" name="6">
For cooperation, please contact Jinhui's personal email: 1193466151@qq.com
<el-collapse-item title="想要合作如何联系我们?" name="6">
合作请联系锦恢的个人邮箱:1193466151@qq.com
</el-collapse-item>
</el-collapse>

BIN
ja/images/.DS_Store vendored

Binary file not shown.

View File

@ -1,71 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="612" height="612" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="174" y1="0" x2="174" y2="348">
<stop offset="0.182" stop-color="#A594F6" />
<stop offset="1" stop-color="#F4E5FF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-346" y="-346" width="348" height="348" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g transform="translate(6 2)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)" transform="translate(293 324)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path d="M0 174C0 77.9024 77.9024 0 174 0C270.098 0 348 77.9024 348 174C348 270.098 270.098 348 174 348C77.9024 348 0 270.098 0 174Z" fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 56)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)" transform="translate(388 129)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

View File

@ -1,71 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="612" height="612" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.468" stop-color="#BFBAF6" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-219" y="-219" width="221" height="221" id="filter_3">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_4" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A8A7F3" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-109" y="-109" width="111" height="111" id="filter_5">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_6" gradientUnits="userSpaceOnUse" x1="174" y1="0" x2="174" y2="348">
<stop offset="0.182" stop-color="#A594F6" />
<stop offset="1" stop-color="#F4E5FF" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-346" y="-346" width="348" height="348" id="filter_7">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
<linearGradient id="gradient_8" gradientUnits="userSpaceOnUse" x1="57" y1="0" x2="57" y2="114">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="0.614" stop-color="#C7BAF8" />
</linearGradient>
<filter color-interpolation-filters="sRGB" x="-112" y="-112" width="114" height="114" id="filter_9">
<feFlood flood-opacity="0" result="BackgroundImageFix_1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="SourceAlpha" />
<feOffset dx="0" dy="4" />
<feGaussianBlur stdDeviation="2" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0" />
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter>
</defs>
<g transform="translate(6 2)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" filter="url(#filter_3)" transform="translate(293 324)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_4)" fill-rule="evenodd" filter="url(#filter_5)" transform="translate(48 269)" />
<path d="M0 174C0 77.9024 77.9024 0 174 0C270.098 0 348 77.9024 348 174C348 270.098 270.098 348 174 348C77.9024 348 0 270.098 0 174Z" fill="url(#gradient_6)" fill-rule="evenodd" filter="url(#filter_7)" transform="translate(188 56)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="url(#gradient_8)" fill-rule="evenodd" filter="url(#filter_9)" transform="translate(388 129)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="600" height="674" viewBox="0 0 600 674" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="110.5" y1="0" x2="110.5" y2="221">
<stop offset="0.441" stop-color="#A8A3FF" />
<stop offset="1" stop-color="#FFFFFF" />
</linearGradient>
<linearGradient id="gradient_3" gradientUnits="userSpaceOnUse" x1="55.5" y1="0" x2="55.5" y2="111">
<stop offset="0" stop-color="#FFFFFF" />
<stop offset="1" stop-color="#A489FB" />
</linearGradient>
<linearGradient id="gradient_5" gradientUnits="userSpaceOnUse" x1="126" y1="0" x2="126" y2="647">
<stop offset="0" stop-color="#FFF2B0" />
<stop offset="0.461" stop-color="#F2B63A" />
</linearGradient>
</defs>
<g>
<g>
<g transform="translate(0 74)">
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="url(#gradient_2)" fill-rule="evenodd" transform="translate(284 417)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="url(#gradient_3)" fill-rule="evenodd" transform="translate(49 374)" />
<path d="M0 182.5C0 81.708 81.708 0 182.5 0C283.292 0 365 81.708 365 182.5C365 283.292 283.292 365 182.5 365C81.708 365 0 283.292 0 182.5Z" fill="url(#gradient_4)" fill-rule="evenodd" transform="translate(179 108)" />
<path d="M215.354 294.309L24.8044 647C24.8044 647 80.3091 362.484 80.3091 362.484C80.9377 359.199 79.5325 355.85 77.4987 355.85C77.4987 355.85 23.6951 355.85 23.6951 355.85C6.50011 355.85 -4.96321 325.459 2.13664 298.669C2.13664 298.669 75.28 23.6938 75.28 23.6938C79.1258 9.28799 87.5569 0 96.8384 0C96.8384 0 252 0 252 0C252 0 178.82 218.868 178.82 218.868C177.71 222.217 179.115 226.45 181.371 226.45C181.371 226.45 197.938 226.45 197.938 226.45C218.571 226.45 229.332 268.404 215.354 294.309C215.354 294.309 215.354 294.309 215.354 294.309Z" fill="url(#gradient_5)" transform="translate(193 0)" />
</g>
<rect width="432" height="432" transform="translate(84 107)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="100%" height="100%" viewBox="0 0 824 834" preserveAspectRatio="xMidYMid meet" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" />
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
</linearGradient>
</defs>
<g>
<g transform="translate(145 58)">
<g>
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="#5A00FF" fill-rule="evenodd" />
<path d="M300 0C465.708 0 600 134.292 600 300C600 300 600 300 600 300C600 465.708 465.708 600 300 600C300 600 300 600 300 600C134.292 600 0 465.708 0 300C0 300 0 300 0 300C0 134.292 134.292 0 300 0Z" fill="url(#gradient_1)" fill-rule="evenodd" />
</g>
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="#FFFFFF" fill-rule="evenodd" transform="translate(294 341)" />
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="#FFFFFF" fill-rule="evenodd" transform="translate(48 269)" />
<path d="M0 182.5C0 81.708 81.708 0 182.5 0C283.292 0 365 81.708 365 182.5C365 283.292 283.292 365 182.5 365C81.708 365 0 283.292 0 182.5Z" fill="#FFFFFF" fill-rule="evenodd" transform="translate(188 39)" />
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="#FFFFFF" fill-rule="evenodd" transform="translate(376 130)" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,41 +0,0 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.9119 99.3171C72.4869 99.9307 74.2828 99.8914 75.8725 99.1264L96.4608 89.2197C98.6242 88.1787 100 85.9892 100 83.5872V16.4133C100 14.0113 98.6243 11.8218 96.4609 10.7808L75.8725 0.873756C73.7862 -0.130129 71.3446 0.11576 69.5135 1.44695C69.252 1.63711 69.0028 1.84943 68.769 2.08341L29.3551 38.0415L12.1872 25.0096C10.589 23.7965 8.35363 23.8959 6.86933 25.2461L1.36303 30.2549C-0.452552 31.9064 -0.454633 34.7627 1.35853 36.417L16.2471 50.0001L1.35853 63.5832C-0.454633 65.2374 -0.452552 68.0938 1.36303 69.7453L6.86933 74.7541C8.35363 76.1043 10.589 76.2037 12.1872 74.9905L29.3551 61.9587L68.769 97.9167C69.3925 98.5406 70.1246 99.0104 70.9119 99.3171ZM75.0152 27.2989L45.1091 50.0001L75.0152 72.7012V27.2989Z" fill="white"/>
</mask>
<g mask="url(#mask0)">
<path d="M96.4614 10.7962L75.8569 0.875542C73.4719 -0.272773 70.6217 0.211611 68.75 2.08333L1.29858 63.5832C-0.515693 65.2373 -0.513607 68.0937 1.30308 69.7452L6.81272 74.754C8.29793 76.1042 10.5347 76.2036 12.1338 74.9905L93.3609 13.3699C96.086 11.3026 100 13.2462 100 16.6667V16.4275C100 14.0265 98.6246 11.8378 96.4614 10.7962Z" fill="#0065A9"/>
<g filter="url(#filter0_d)">
<path d="M96.4614 89.2038L75.8569 99.1245C73.4719 100.273 70.6217 99.7884 68.75 97.9167L1.29858 36.4169C-0.515693 34.7627 -0.513607 31.9063 1.30308 30.2548L6.81272 25.246C8.29793 23.8958 10.5347 23.7964 12.1338 25.0095L93.3609 86.6301C96.086 88.6974 100 86.7538 100 83.3334V83.5726C100 85.9735 98.6246 88.1622 96.4614 89.2038Z" fill="#007ACC"/>
</g>
<g filter="url(#filter1_d)">
<path d="M75.8578 99.1263C73.4721 100.274 70.6219 99.7885 68.75 97.9166C71.0564 100.223 75 98.5895 75 95.3278V4.67213C75 1.41039 71.0564 -0.223106 68.75 2.08329C70.6219 0.211402 73.4721 -0.273666 75.8578 0.873633L96.4587 10.7807C98.6234 11.8217 100 14.0112 100 16.4132V83.5871C100 85.9891 98.6234 88.1786 96.4586 89.2196L75.8578 99.1263Z" fill="#1F9CF0"/>
</g>
<g style="mix-blend-mode:overlay" opacity="0.25">
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.8511 99.3171C72.4261 99.9306 74.2221 99.8913 75.8117 99.1264L96.4 89.2197C98.5634 88.1787 99.9392 85.9892 99.9392 83.5871V16.4133C99.9392 14.0112 98.5635 11.8217 96.4001 10.7807L75.8117 0.873695C73.7255 -0.13019 71.2838 0.115699 69.4527 1.44688C69.1912 1.63705 68.942 1.84937 68.7082 2.08335L29.2943 38.0414L12.1264 25.0096C10.5283 23.7964 8.29285 23.8959 6.80855 25.246L1.30225 30.2548C-0.513334 31.9064 -0.515415 34.7627 1.29775 36.4169L16.1863 50L1.29775 63.5832C-0.515415 65.2374 -0.513334 68.0937 1.30225 69.7452L6.80855 74.754C8.29285 76.1042 10.5283 76.2036 12.1264 74.9905L29.2943 61.9586L68.7082 97.9167C69.3317 98.5405 70.0638 99.0104 70.8511 99.3171ZM74.9544 27.2989L45.0483 50L74.9544 72.7012V27.2989Z" fill="url(#paint0_linear)"/>
</g>
</g>
<defs>
<filter id="filter0_d" x="-8.39411" y="15.8291" width="116.727" height="92.2456" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset/>
<feGaussianBlur stdDeviation="4.16667"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="overlay" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="60.4167" y="-8.07558" width="47.9167" height="116.151" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset/>
<feGaussianBlur stdDeviation="4.16667"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="overlay" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<linearGradient id="paint0_linear" x1="49.9392" y1="0.257812" x2="49.9392" y2="99.7423" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 KiB

View File

@ -1,127 +0,0 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: "OpenMCP"
text: "エレガントな開発者向けのMCPデバッガーとSDK"
tagline: 大規模言語モデルからエージェントまでの最後の一歩を埋める
actions:
- theme: brand
text: OpenMCPプラグイン
link: ./plugin-tutorial
- theme: alt
text: openmcp-sdk
link: ./sdk-tutorial
- theme: alt
text: GitHub
link: https://github.com/LSTM-Kirigaya/openmcp-client
features:
- icon:
src: /images/icons/vscode.svg
height: 48px
alt: 統合デバッグ環境
title: 統合デバッグ環境
details: インスペクターとMCPクライアント機能を組み合わせて、シームレスな開発とテストを実現します。
- icon:
src: /images/icons/openmcp-edge.svg
height: 48px
alt: 完全なプロジェクトレベルのコントロールパネルを提供する
title: 包括的なプロジェクト管理
details: 完全なプロジェクトレベルのコントロールパネルを提供し、効率的なMCPプロジェクトの監視を実現します。
- icon:
src: /images/icons/openmcp-sdk.svg
height: 48px
alt: 完全なプロジェクトレベルのコントロールパネルを提供する
title: 完全なデプロイメントソリューション
details: テストが完了したエージェントをopenmcp-sdkを通じてあなたのアプリケーションやサーバーにデプロイします。
---
<br><br>
<h2 id="home-0">
あなたのMCPエージェント開発のお手伝いをします
<br>
<span>MCPエージェント開発に楽しさと利便性をもたらす</span>
</h2>
<div class="bilibili-player-container" style="display:flex; width: 100%; justify-content: center;">
<iframe width="90%" height="580" src="https://www.youtube.com/embed/S7igsEhcLiw?si=6sqvbYJxSRoFS26g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div>
<br>
<h2 id="home-1">
OpenMCPは誰のためのものですか
<br>
<span>OpenMCPの開発は...</span>
</h2>
<br>
<KTab class="home-tab">
<TwoSideLayout
label="プロのソフトウェアエンジニア"
:texts="[
'テストを早期に行うことで、開発とテストを統合し、サードパーティのソフトウェアを開く必要がありません。非常に豊富な機能を提供します。',
'左側のパネルで自由かつエレガントにあなたのエージェントを管理、デバッグ、テストします。',
'大規模言語モデル呼び出しツールのすべての詳細が一目でわかります。不満な呼び出し結果はワンクリックで再現できます。',
'すべての会話で各種パフォーマンス指標が表示され、コスト管理が容易になります。',
'システムプロンプト管理パネルを使用すると、MCPサーバーとシステムプロンプトを使って簡単にエージェントアプリケーションを構築できます。',
]"
image="./images/openmcp.xml.png"
/>
<TwoSideLayout
label="オープンソースコミュニティの愛好家"
:texts="[
'テストを早期に行うことで、開発とテストを統合し、サードパーティのソフトウェアを開く必要がありません。非常に豊富な機能を提供します。',
'OpenMCPは完全にオープンソースです。あなたはこの製品を無料で試用できるだけでなく、私たちに参加してエージェントに関するあなたの独創的なアイデアを実現することもできます。',
'技術の詳細は完全に公開されているので、あなたのアイデアやトークンが盗用される心配はありません。',
'永続化可能なシステムプロンプト管理パネルを使用すると、実際のMCPサーバーのシステムプロンプトをテストし、コミュニティ内で共有することができます。',
'すべてのテストの詳細は100Gitのバージョン管理に従い、あなたのテスト結果を簡単に共有し、他の人のMCPプロジェクトをゼロコストで再現することができます。'
]"
image="./images/openmcp.chatbot.png"
/>
<TwoSideLayout
label="AI研究開発科学者"
:texts="[
'テストを早期に行うことで、開発とテストを統合し、サードパーティのソフトウェアを開く必要がありません。非常に豊富な機能を提供します。',
'数行のコードで、あなたの研究成果をすぐにMCPサーバーに変換し、任意の大規模言語モデルに接続して、ユーザーフレンドリーなインターフェースを実現できます。',
'すべての実験データと設定パラメータは自動的にGitバージョン管理システムに組み込まれ、研究成果の追跡と再現が可能になり、学術交流や論文の再現が容易になります。',
'OpenMCPをベースにしてあなたのデモをすばやく完成させ、イベーションから実現までの距離を短縮します。',
]"
image="./images/openmcp.resource.png"
/>
</KTab>
<br>
<h2 id="home-2">
よくある質問
<br>
<span>あなたの質問をお待ちしています</span>
</h2>
<el-collapse>
<el-collapse-item title="OpenMCPは何に適していますか" name="1">
その名前の通り、OpenMCPは開発者向けのMCPデバッガーとSDKであり、AIエージェントの全工程の開発コストと開発者の負担を軽減することに取り組んでいます。OpenMCPを通じて、実生活のシーンで問題を解決し、作業時間を短縮できるMCPツールを作成したり、エンジニアや研究開発科学者がより早くデモを提供し、このビジョンを一般に知らしめることが私たちの使命です。
</el-collapse-item>
<el-collapse-item title="OpenMCPは無料ですか" name="2">
はい、OpenMCPは完全にオープンソースです。あなたはこの製品を無料で使用できるだけでなく、私たちに参加してエージェントに関するあなたの独創的なアイデアを実現することもできます。OpenMCPのタスクは、MCPに関するエコシステムを構築することです。私たちは、MCPの開発は今後しばらくの間高度にカスタマイズされた作業になると考えているため、現在の重点はすぐに何でもできるようなエージェントを作ることではなく、着実に関連するエコシステムやインフラストラクチャを構築することです。
</el-collapse-item>
<el-collapse-item title="OpenMCPは何に適さないですか" name="3">
OpenMCPを使って何でもできる汎用的なAIエージェントを開発しようとする場合は、このサイトを開くのではなく、すべての資金を量子コンピュータの研究開発に投資するべきです。この時代に全分野の汎用AIエージェントを作ることは、確率的に電話詐欺に収束することを忘れないでください。
</el-collapse-item>
<el-collapse-item title="OpenMCPは誰が開発していますか" name="4">
<p>OpenMCPは、LSTM-Kirigaya(錦恢)によって最初に主導され、3D関連の作業用のMCPテストツールを構築するために開発されました。その主な参加者は、大手企業の従業員、大学のコンピュータ関連学科の学生、およびいくつかのオープンソースコミュニティの積極的な貢献者です。</p>
<p>身元は重要ではありません。私がとても好きな一言をあなたに贈ります:「できるかどうかを答えるのではなく、好きかどうかを答えてください」。</p>
<img src="https://pica.zhimg.com/80/v2-3666e84b2f92bf444a5eb64fb9d08e71_1440w.png" style="max-width: 500px;margin-top:10px;"/>
</el-collapse-item>
<el-collapse-item title="私たちに参加したり、議論に参加するにはどうすればいいですか?" name="5">
<a href="https://kirigaya.cn/openmcp/preview/join.html" target="_blank">OpenMCPに参加する</a> を通じて、OpenMCPのメンテナンスと開発に参加する方法を学ぶことができます。<a href="https://kirigaya.cn/openmcp/preview/channel.html" target="_blank">リソースチャンネル</a> を通じて私たちの連絡先を取得できます。現在主なコミュニティは3つあります。QQグループ782833642 、 <a href="https://discord.com/invite/SKTZRf6NzU" target="_blank">OpenMCP Discordチャンネル</a><a href="https://www.zhihu.com/ring/host/1911121615279849840" target="_blank">知乎サークル【OpenMCP博物館】</a>
</el-collapse-item>
<el-collapse-item title="協力を希望する場合はどうすれば連絡できますか?" name="6">
協力に関しては、錦恢の個人メール1193466151@qq.comまでご連絡ください。
</el-collapse-item>
</el-collapse>

View File

@ -1,226 +0,0 @@
# MCP 基本概念
## はじめに
[[what-is-mcp|前回の記事]]では、MCPの定義と基本的な組織構造について簡単に紹介しました。開発者として最も注目すべきは、自社の業務とシナリオに基づいて必要なMCPサーバーをカスタマイズ開発する方法です。これにより、任意のMCPクライアントに直接接続して、カスタマイズされたインタラクション能力を大規模モデルに提供できます。
MCPサーバーの開発方法を説明する前に、いくつかの基本概念を明確にしておく必要があると思います。
## Resources、Prompts、Tools
[MCPクライアントプロトコル](https://modelcontextprotocol.io/clients)では、MCPプロトコルの3つの重要な能力カテゴリについて説明されています
- Resoucesローカルリソースをカスタマイズしてリクエスト・アクセスする機能。ファイルシステム、データベース、現在のコードエディタ内のファイルなど、ウェブアプリでは通常アクセスできない**静的リソース**を指します。追加のresourcesは大規模モデルに送信されるコンテキストを豊富にし、AIからより正確な回答を得られます。
- Prompts特定のシナリオでAIが採用可能なプロンプトをカスタマイズします。例えば、AIに特定のフォーマットで内容を返させる必要がある場合、カスタムプロンプトを提供できます。
- ToolsAIが使用できるツールで、関数である必要があります。ホテルの予約、ウェブページの開閉、照明のオンオフなどのカプセル化された関数がtoolとなります。大規模モデルはfunction callingの方法でこれらのtoolsを使用します。Toolsにより、AIが直接コンピュータを操作したり、現実世界とインタラクションしたりできるようになります。
フロントエンド・バックエンド開発経験のある方は、Resoucesを「大規模モデルに付与する追加の読み取り専用権限」、Toolsを「大規模モデルに付与する追加の読み書き権限」と考えることができます。
MCPクライアントClaude Desktop、5ireなどは既に上記のフロントエンドロジックを実装しています。具体的にどのようなリソースやツールを提供するかは、開発者の想像力次第です。つまり、多彩なMCP Serverを開発することで、大規模モデルにより興味深い作業を行わせることができます。
ただし、現在ほぼすべての大規模モデルはopenaiプロトコルをアクセスポイントとして採用している点に注意が必要です。openaiプロトコルとは何でしょうか
## openaiプロトコル
PythonやTypeScriptでアプリを開発する際、通常はopenaiという名前のライブラリをインストールし、使用するモデルベンダー、モデルのベースURL、使用するモデルタイプを入力して大規模モデルに直接アクセスします。各モデルプロバイダーもこのライブラリとプロトコルをサポートする必要があります。
例えばPythonでdeepseekのサービスにアクセスする場合、次のようにできます
```python
from openai import OpenAI
client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=False
)
print(response.choices[0].message.content)
```
このcreate関数の中身を見ると、openaiプロトコルが大規模モデルプロバイダーに要求する機能が非常に多いことがわかります
```python
@overload
def create(
self,
*,
messages: Iterable[ChatCompletionMessageParam],
model: Union[str, ChatModel],
audio: Optional[ChatCompletionAudioParam] | NotGiven = NOT_GIVEN,
frequency_penalty: Optional[float] | NotGiven = NOT_GIVEN,
function_call: completion_create_params.FunctionCall | NotGiven = NOT_GIVEN,
functions: Iterable[completion_create_params.Function] | NotGiven = NOT_GIVEN,
logit_bias: Optional[Dict[str, int]] | NotGiven = NOT_GIVEN,
logprobs: Optional[bool] | NotGiven = NOT_GIVEN,
max_completion_tokens: Optional[int] | NotGiven = NOT_GIVEN,
max_tokens: Optional[int] | NotGiven = NOT_GIVEN,
metadata: Optional[Metadata] | NotGiven = NOT_GIVEN,
modalities: Optional[List[Literal["text", "audio"]]] | NotGiven = NOT_GIVEN,
n: Optional[int] | NotGiven = NOT_GIVEN,
parallel_tool_calls: bool | NotGiven = NOT_GIVEN,
prediction: Optional[ChatCompletionPredictionContentParam] | NotGiven = NOT_GIVEN,
presence_penalty: Optional[float] | NotGiven = NOT_GIVEN,
reasoning_effort: Optional[ReasoningEffort] | NotGiven = NOT_GIVEN,
response_format: completion_create_params.ResponseFormat | NotGiven = NOT_GIVEN,
seed: Optional[int] | NotGiven = NOT_GIVEN,
service_tier: Optional[Literal["auto", "default"]] | NotGiven = NOT_GIVEN,
stop: Union[Optional[str], List[str], None] | NotGiven = NOT_GIVEN,
store: Optional[bool] | NotGiven = NOT_GIVEN,
stream: Optional[Literal[False]] | NotGiven = NOT_GIVEN,
stream_options: Optional[ChatCompletionStreamOptionsParam] | NotGiven = NOT_GIVEN,
temperature: Optional[float] | NotGiven = NOT_GIVEN,
tool_choice: ChatCompletionToolChoiceOptionParam | NotGiven = NOT_GIVEN,
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
top_logprobs: Optional[int] | NotGiven = NOT_GIVEN,
top_p: Optional[float] | NotGiven = NOT_GIVEN,
user: str | NotGiven = NOT_GIVEN,
web_search_options: completion_create_params.WebSearchOptions | NotGiven = NOT_GIVEN,
# 以下の引数は、kwargsを介して利用できない追加のAPIパラメータを渡す必要がある場合に使用します。
# ここで指定された追加の値は、クライアントで定義された値やこのメソッドに渡された値よりも優先されます。
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> ChatCompletion:
```
上記のシグネチャから、`temperature``top_p`など、いくつか見覚えのあるパラメータが確認できます。多くの大規模モデル使用ソフトウェアでは、このパラメータを調整できるようになっています。例えば5ireでは、コンテンツのランダム性は`temperature`パラメータのグラフィカル表示です。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-9f8544aa917e8c128fc194adeb7161cd_1440w.png" style="width: 100%;"/>
</div>
実際、ご覧の通り、普通の呼び出しに関わる調整可能なパラメータは非常に多岐にわたります。すべてのパラメータの中で、`tools`というパラメータに注目してください:
```python
@overload
def create(
self,
*,
messages: Iterable[ChatCompletionMessageParam],
model: Union[str, ChatModel],
audio: Optional[ChatCompletionAudioParam] | NotGiven = NOT_GIVEN,
# ここを見て
tools: Iterable[ChatCompletionToolParam] | NotGiven = NOT_GIVEN,
) -> ChatCompletion:
```
## tool_callsフィールド
上記のopenaiプロトコルには、toolsというパラメータがあります。toolsは、大規模モデルプロバイダーがfunction callingという特性をサポートする必要があることを意味しますMCPプロトコルと完全互換。toolsが空でない場合、chat関数の戻り値には特別なフィールド`tool_calls`が含まれます。以下は、私が作成した天気を問い合わせるコードです:
```python
from openai import OpenAI
client = OpenAI(
api_key="Deepseek API",
base_url="https://api.deepseek.com"
)
# tools関数/ツールリスト)を定義
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "指定された場所の天気を取得",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "都市、例えば杭州、北京、上海",
}
},
"required": ["location"],
},
},
}
]
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "あなたは役立つAIです"},
{"role": "user", "content": "今日の杭州の天気は?"},
],
tools=tools, # toolsパラメータを渡す
tool_choice="auto", # オプション:特定のツールの呼び出しを強制するかどうかを制御
stream=False,
)
print(response.choices[0].message)
```
上記のコードを実行すると、次のような戻り値が得られます:
```python
ChatCompletionMessage(
content='',
refusal=None,
role='assistant',
annotations=None,
audio=None,
function_call=None,
tool_calls=[
ChatCompletionMessageToolCall(
id='call_0_baeaba2b-739d-40c2-aa6c-1e61c6d7e855',
function=Function(
arguments='{"location":"杭州"}',
name='get_current_weather'
),
type='function',
index=0
)
]
)
```
上記の`tool_calls`から、大規模モデルが提供されたツールをどのように使用したいかがわかります。注意点として、コンテキストの制限により、現在1つの質問で大規模モデルが呼び出せるツールの上限は通常100個を超えません。これは大規模モデルプロバイダーのコンテキストサイズに関係します。あ、そうそう、友情提示ですが、MCPクライアントで大規模モデルを使用して問題を解決する際、同時にアクティブなMCP Serverが多いほど、消費されるtokenも多くなりますよ :D
現在のopenaiプロトコルでは、toolsは関数クラスの呼び出しのみをサポートしています。関数クラスの呼び出しは、Resourcesの効果をシミュレートできる場合があります。例えばリソースを取得する場合、それをtoolとして記述できます。したがって、通常の場合、MCP Serverを開発する際は、Toolsのみを開発するのが最善です。他の2つの機能はまだ広くサポートされていません。
## Inspectorを使用したデバッグ
Claudeがネイティブで提供するMCPプロトコルは、公式が提供するInspectorでデバッグできます。[[first-mcp|最初のMCP]]の例では、次のようにデバッグできます。コマンドラインで次のコマンドを入力してInspectorを起動します
```bash
mcp dev main.py
```
これによりフロントエンドサーバーが起動し、`http://localhost:5173/`を開くとinspectorのデバッグインターフェースが表示されます。まず左側の`Connect`をクリックしてserver.pyを実行し、stdioを通信パイプとして使用してwebと通信を確立します。
さあ、楽しくデバッグを始められます。Inspectorは主に3つのセクションを提供し、それぞれResources、Prompts、Toolsに対応しています。
まずResourcesを見てみましょう。「Resource Templates」をクリックすると、登録されているすべてのResourceがリスト表示されます。例えば上記で定義した`get_greeting`は、パラメータを入力して実行することで、この関数が正常に動作するかどうかを確認できます。(通常、このリソースプロトコルはリモートデータベースまたはマイクロサービスにアクセスします)
<div align=center>
<img src="https://picx.zhimg.com/80/v2-71fc1ad813cdbf7ecec24d878c343b96_1440w.png" style="width: 100%;"/>
</div>
Prompts側は比較的シンプルで、定義済みパラメータを入力するだけで正常な戻り値を取得できます。
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-4f42899ba1163922ac2347f7cebe5362_1440w.png" style="width: 100%;"/>
</div>
Tools側は、これからデバッグの中心となる部分です。前の章で説明したように、MCPプロトコルのPromptsとResourcesは現在openaiプロトコルや主要なMCPクライアントで広くサポートされていないため、サーバー側の主要なビジネスはtoolsの作成に集中すべきです。
ここで提供するtoolは、簡単な加算を実装するものです。非常にシンプルで、1と2を入力すると、結果が3であることが直接確認できます。今後、天気予報にアクセスできるtoolを開発する予定ですので、その際はこのようなウィンドウが天気情報の取得が正常かどうかをデバッグするのに非常に役立ちます。
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-4164a900198a70a158ae441f9e441d07_1440w.png" style="width: 100%;"/>
</div>
## まとめ
この記事では、MCP内部のいくつかの基本概念について簡単に理解しました。これらの概念は、MCPサーバーを開発する上で非常に有益だと思いますので、まず説明する必要があると考えました。
次の記事では、MCPの不思議な世界を探求し、AI Agentの時代がまもなく到来することをお伝えします。

View File

@ -1,339 +0,0 @@
# Goで実装するNeo4jの読み取り専用MCPサーバーSSE
[今回のチュートリアル動画](https://www.bilibili.com/video/BV1g8TozyEE7/)
## はじめに
このチュートリアルでは、Go言語を使ってNeo4jデータベースにアクセスできるMCPサーバーを書く方法をデモンストレーションします。実装が完了すると、クエリコードを一切書かずに、大規模言語モデルに問い合わせるだけでサーバーの状況を把握できるようになります。
従来の接続方法とは異なり、今回はSSEServer-Sent Events方式でサーバーの作成と接続を行います。
今回のチュートリアルのコードhttps://github.com/LSTM-Kirigaya/openmcp-tutorial/tree/main/neo4j-go-server
このコードをダウンロードすることをお勧めします。なぜなら、私が準備したデータベースファイルが含まれているからです。そうでないと、自分でデータをモックする必要があります。
## 1. 準備
プロジェクトの構造は以下の通りです:
```bash
📦neo4j-go-server
┣ 📂util
┃ ┗ 📜util.go # ユーティリティ関数
┣ 📜main.go # メイン関数
┗ 📜neo4j.json # データベース接続のアカウント情報
```
まずGoプロジェクトを作成します
```bash
mkdir neo4j-go-server
cd neo4j-go-server
go mod init neo4j-go-server
```
## 2. データベースの初期化を完了する
### 2.1 Neo4jのインストール
まず、私のチュートリアルに従ってローカルまたはサーバーにNeo4jデータベースを設定します。ここではチュートリアルですので、このチュートリアルの最初の2ステップだけを完了すれば十分です[Neo4jデータベースのインストールと設定](https://kirigaya.cn/blog/article?seq=199)。binパスを環境変数に追加し、パスワードをopenmcpに設定します。
次に、main.goと同じ階層にneo4j.jsonを作成し、Neo4jデータベースの接続情報を記入します
```json
{
"url" : "neo4j://localhost:7687",
"name" : "neo4j",
"password" : "openmcp"
}
```
### 2.2 事前に準備されたデータのインポート
インストールが完了したら、私が事前に準備したデータをインポートできます。これらのデータは私の個人ウェブサイトの一部のデータを匿名化した要約です。自由に使用してください。ダウンロードリンク:[neo4j.db](https://github.com/LSTM-Kirigaya/openmcp-tutorial/releases/download/neo4j.db/neo4j.db)。ダウンロードが完了したら、以下のコマンドを実行します:
```bash
neo4j stop
neo4j-admin load --database neo4j --from neo4j.db --force
neo4j start
```
その後、データベースにログインすると、私が準備したデータを見ることができます:
```bash
cypher-shell -a localhost -u neo4j -p openmcp
```
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-4b53ad6a355c05d99c7ed18687ced717_1440w.png" style="width: 80%;"/>
</div>
### 2.3 Goからデータベースへの接続性を検証する
データベースの接続性とGoのデータベースドライバーが正常に動作していることを確認するために、まずデータベースアクセスの最小システムを書く必要があります。
まず、Neo4jのv5バージョンのGoドライバーをインストールします
```bash
go get github.com/neo4j/neo4j-go-driver/v5
```
`util.go`に以下のコードを追加します:
```go
package util
import (
"context"
"encoding/json"
"fmt"
"os"
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
)
var (
Neo4jDriver neo4j.DriverWithContext
)
// Neo4jサーバーへの接続を作成
func CreateNeo4jDriver(configPath string) (neo4j.DriverWithContext, error) {
jsonString, _ := os.ReadFile(configPath)
config := make(map[string]string)
json.Unmarshal(jsonString, &config)
// fmt.Printf("url: %s\nname: %s\npassword: %s\n", config["url"], config["name"], config["password"])
var err error
Neo4jDriver, err = neo4j.NewDriverWithContext(
config["url"],
neo4j.BasicAuth(config["name"], config["password"], ""),
)
if err != nil {
return Neo4jDriver, err
}
return Neo4jDriver, nil
}
// 読み取り専用のCypherクエリを実行
func ExecuteReadOnlyCypherQuery(
cypher string,
) ([]map[string]any, error) {
session := Neo4jDriver.NewSession(context.TODO(), neo4j.SessionConfig{
AccessMode: neo4j.AccessModeRead,
})
defer session.Close(context.TODO())
result, err := session.Run(context.TODO(), cypher, nil)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
var records []map[string]any
for result.Next(context.TODO()) {
records = append(records, result.Record().AsMap())
}
return records, nil
}
```
main.goに以下のコードを追加します
```go
package main
import (
"fmt"
"neo4j-go-server/util"
)
var (
neo4jPath string = "./neo4j.json"
)
func main() {
_, err := util.CreateNeo4jDriver(neo4jPath)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Neo4j driver created successfully")
}
```
メインプログラムを実行してデータベースの接続性を検証します:
```bash
go run main.go
```
`Neo4j driver created successfully`と出力されれば、データベースの接続性検証は成功です。
## 3. MCPサーバーの実装
GoのMCP SDKで最も有名なのはmark3labs/mcp-goです。これを使用します。
> mark3labs/mcp-goのデモはhttps://github.com/mark3labs/mcp-goにあり、非常にシンプルです。ここでは直接使用します。
まずインストールします:
```bash
go get github.com/mark3labs/mcp-go
```
次に`main.go`に以下のコードを追加します:
```go
// ... 既存のコード ...
var (
addr string = "localhost:8083"
)
func main() {
// ... 既存のコード ...
s := server.NewMCPServer(
"読み取り専用Neo4jサーバー",
"0.0.1",
server.WithToolCapabilities(true),
)
srv := server.NewSSEServer(s)
// executeReadOnlyCypherQueryツールのスキーマを定義
executeReadOnlyCypherQuery := mcp.NewTool("executeReadOnlyCypherQuery",
mcp.WithDescription("読み取り専用のCypherクエリを実行"),
mcp.WithString("cypher",
mcp.Required(),
mcp.Description("Cypherクエリ文、読み取り専用でなければなりません"),
),
)
// 実際の関数と宣言されたスキーマをバインド
s.AddTool(executeReadOnlyCypherQuery, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args, ok := request.Params.Arguments.(map[string]interface{})
if !ok {
return mcp.NewToolResultText(""), fmt.Errorf("無効な引数の型")
}
cypher, ok := args["cypher"].(string)
if !ok {
return mcp.NewToolResultText(""), fmt.Errorf("cypher引数が文字列ではありません")
}
result, err := util.ExecuteReadOnlyCypherQuery(cypher)
fmt.Println(result)
if err != nil {
return mcp.NewToolResultText(""), err
}
return mcp.NewToolResultText(fmt.Sprintf("%v", result)), nil
})
// http://localhost:8083/sseでサービスを開始
fmt.Printf("サーバーがhttp://%s/sseで起動しました\n", addr)
srv.Start(addr)
}
```
go run main.goを実行すると、以下の情報が表示されます
```
Neo4j driver created successfully
サーバーがhttp://localhost:8083/sseで起動しました
```
これで、MCPサーバーがローカルの8083ポートで起動しました。
## 4. OpenMCPを使用したデバッグ
### 4.1 ワークスペースにSSEデバッグプロジェクトを追加
次に、OpenMCPを使用してデバッグを行います。まず、VSコードの左側にあるOpenMCPアイコンをクリックしてコントロールパネルに入ります。https://github.com/LSTM-Kirigaya/openmcp-tutorial/tree/main/neo4j-go-server からこのプロジェクトをダウンロードした場合、【MCP接続ワークスペース】に既に作成済みのデバッグプロジェクト【読み取り専用Neo4jサーバー】が表示されます。完全に自分でこのプロジェクトを作成した場合は、以下のボタンから接続を追加し、SSEを選択してhttp://localhost:8083/sseを入力し、OAuthは空のままにします。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-31a01f1253dfc8c42e23e05b1869a932_1440w.png" style="width: 80%;"/>
</div>
### 4.2 ツールのテスト
MCPサーバーを初めてデバッグする際に最初に行うべきことは、MCPツールを動作させることです。新しいタブを作成し、ツールを選択し、以下の図のツールをクリックして、`CALL db.labels() YIELD label RETURN label`と入力します。この文はすべてのノードタイプをリストアップするために使用されます。以下の結果が出力されれば、現在のリンクは有効で問題ありません。
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-dd59d9c96ecb455e527ab8aa7f963908_1440w.png" style="width: 100%;"/>
</div>
### 4.3 大規模言語モデルの機能範囲を理解し、プロンプトで知識をカプセル化する
それでは、面白いことをしてみましょう次に、大規模言語モデルの能力範囲をテストします。なぜなら、Neo4jは特殊なデータベースであり、一般的な大規模言語モデルはその使用方法を知らないかもしれないからです。新しいタブを作成し、「インタラクティブテスト」をクリックし、まず簡単な質問をします
```
最新の10件のコメントを見つけてください
```
結果は以下の通りです:
<div align=center>
<img src="https://picx.zhimg.com/80/v2-44fab30650051db4e3b94de34275af3a_1440w.png" style="width: 100%;"/>
</div>
大規模言語モデルがクエリしたードタイプが間違っていることがわかります。私が提供した例では、コメントを表すードはBlogCommentであり、Commentではありません。つまり、大規模言語モデルはデータベースクエリの一般的な方法論を掌握していません。これが現在わかっているその能力範囲です。次に、私たちの経験と知識を段階的に注入します。うむ、システムプロンプトを通じて完了します。
### 4.4 大規模言語モデルにデータベースノードを見つける方法を教える
よく考えてみてください。エンジニアとして、私たちはどのようにしてコメントのードがBlogCommentであることを知るのでしょうか一般的に、現在のデータベースのすべてのードタイプをリストアップし、命名から推測します。たとえば、このデータベースの場合、私はまず以下のようなCypherクエリを入力します
```sql
CALL db.labels() YIELD label RETURN label
```
その出力は4.2の図にあります。英語が得意であれば、BlogCommentがおそらくブログコメントを表すードであることがわかるでしょう。さて、この方法論をシステムプロンプトに注入し、この知識をカプセル化します。以下の図の下部のボタンをクリックして、【システムプロンプト】に入ります
<div align=center>
<img src="https://pica.zhimg.com/80/v2-e0fdd265e53dd354163358be1f5cc3f6_1440w.png" style="width: 100%;"/>
</div>
新しいプロンプト【neo4j】を作成し、入力します
```
あなたはneo4jクエリが得意なインテリジェントエージェントです。ユーザーからのクエリリクエストに対して、対応するデータベースードが何であるか必ずしも知っているわけではありません。その場合、まずすべてのードタイプをリストアップし、その中からユーザーの質問に最も一致すると考えるードを見つける必要があります。たとえば、ユーザーが特定の条件に合致する「記事」を見たいと尋ねた場合、記事ードのタイプが何であるか知らないので、まずすべてのードをリストアップする必要があります。
```
保存をクリックし、【インタラクティブテスト】で先ほどの質問を繰り返します:
```
最新の10件のコメントを見つけてください
```
大規模言語モデルの回答は以下の通りです:
<div align=center>
<img src="https://picx.zhimg.com/80/v2-ccf4a5ecb5691620fca659dcd60d2e38_1440w.png" style="width: 80%;"/>
</div>
どうでしょうずっと良くなったのではないでしょうか大規模言語モデルはBlogCommentードを正しく見つけ、対応するデータを返しました。
しかし、まだ完全には正しくありません。なぜなら、私たちが要求したのは最新の10件のコメントですが、大規模言語モデルが返したのは実際には最も古い10件のコメントです。大規模言語モデルの呼び出しの詳細を開くと、大規模言語モデルは`ORDER BY comment.createdAt`を使用して実装していることがわかります。しかし、問題は、私たちのデータベースでは、コメントが作成された時間を記録するフィールドはcreatedAtではなく、createdTimeであることです。これは、大規模言語モデルがードのフィールドを知らないことを知らず、「幻覚」を起こし、適当なフィールドを入力したことを意味します。
大規模言語モデルは自分が知らないことを明示的に言うことはありません。錦恢研究生のOODに関する研究は、このことの本質的な理由を説明できます[EDLEvidential Deep Learning原理とコード実装](https://kirigaya.cn/blog/article?seq=154)。もしあなたの好奇心が数学の基礎力に匹敵するなら、この記事を試してみてください。とにかく、あなたが知っておくべきことは、大規模言語モデルが自分が知らないことに対して幻覚を起こすからこそ、私たちが経験を注入する操作の余地があるということです。
### 4.5 大規模言語モデルにデータベースノードのフィールドを見つける方法を教える
上記の試みを通じて、私たちは終点まであと少しであることを知りました。それは、大規模言語モデルに、私たちのデータベースでは、コメントが作成された時間を記録するフィールドはcreatedAtではなく、createdTimeであることを教えることです。
フィールドを識別する知識について、先ほどのシステムプロンプトを改良します:
```
あなたはneo4jクエリが得意なインテリジェントエージェントです。ユーザーからのクエリリクエストに対して、対応するデータベースードが何であるか必ずしも知っているわけではありません。その場合、まずすべてのードタイプをリストアップし、その中からユーザーの質問に最も一致すると考えるードを見つける必要があります。たとえば、ユーザーが特定の条件に合致する「記事」を見たいと尋ねた場合、記事ードのタイプが何であるか知らないので、まずすべてのードをリストアップする必要があります。
より具体的なクエリの場合、まず1つまたは2つの事例をクエリして、現在のタイプにどのようなフィールドがあるかを確認する必要があります。たとえば、ユーザーが最新の記事を尋ねた場合、記事ードのどのフィールドが「作成時間」を表すか知らないので、まず1つまたは2つの記事ードをリストアップし、その中にどのようなフィールドがあるかを確認し、その後、最新の10件の記事をクエリする必要があります。
```
結果は以下の通りです:

View File

@ -1,28 +0,0 @@
---
next:
text: Pythonで実装した天気情報MCPサーバーSTDIO
link: '/plugin-tutorial/examples/python-simple-stdio'
---
# MCPサーバー開発事例
## Python
- [Pythonで実装した天気情報MCPサーバーSTDIO](./python-simple-stdio)
- [Pythonで実装した汎用フォーム入力MCPSTDIO](./python-form-stdio)
- [Pythonで実装したBlenderベースのMCPSTDIO](./python-blender-stdio)
- [Pythonで実装したCadence EDA用MCPSTDIO](./python-cadence-stdio)
- FFmpegベースMCPによる対話型動画編集
- RAGベースMCPによるナレッジベース注入
- Stable Diffusion用MCPサーバーの実装
## Nodejs
- [TypeScriptで実装したcrawl4aiベースの超機能ウェブクローラーMCPSTDIO](./typescript-crawl4ai-stdio)
## Go
- [Goで実装したNeo4j用読み取り専用MCPサーバーSSE](./go-neo4j-sse)
## Java
- [Javaで実装したドキュメントデータベース用読み取り専用MCPHTTP](./java-es-http)
## 認証
- [SSE方式OAuth2認証MCPサーバー事例](./sse-oauth2)

View File

@ -1,321 +0,0 @@
# Pythonで実装する天気情報MCPサーバー
## フック
待って、始める前に小さな例を見てみましょう。来週「アークナイツ」の「錆びた影、新生」コスプレイベントに行く予定なので、土曜日の杭州の天気を知りたいです。AIに土曜日の天気を聞くと、以下のような回答が返ってきました
<div align=center>
<img src="https://picx.zhimg.com/80/v2-4c623ac6897e12093535b0d9ed9cf242_1440w.png" style="width: 100%;"/>
</div>
これはダメですね。皆さんもよくあると思いますが、AIは「魚の釣り方を教える」ことが多く、時には単に結果が知りたいだけの退屈な日常の用事もあります。
実際、天気予報を実装するプログラムはたくさんあります。では、完成した天気予報プログラムをAIに接続し、実際の天気を教えてもらって、明日のコスプレイベントの服装を選ぶにはどうすればよいでしょうか
直接関数を書いてfunction callingを使うのは少し面倒です。AIプロバイダーのAPI呼び出しやタスクループの構築、テキストレンダリングなど、多くの技術的な詳細を検討する必要があり、貴重な時間を浪費します。MCPは私たちに救いの道を与えてくれます。今日のチュートリアルでは、簡単なMCPサーバーを書いて、AIに天気予報を知る能力を与える方法を教えます。
## はじめに
👉 [前回のナビゲーション](https://zhuanlan.zhihu.com/p/32593727614)
前回はMCPの基礎を簡単に説明しました。今回は、自分たちのMCPサーバーを開発し、既存のアプリケーション、サービス、ハードウェアなどをAIに接続します。これにより、AIからエンドアプリケーションへの最後の1キロメートルを完了します。
「工欲善其事、必先利其器」。よりエレガントで楽しくMCPサーバーを開発するために、開発プロセスでプログラムの変更を確認し、直接AIに接続してツールの有効性を検証できる優れたテストツールが必要です。
そこで、私は最近オールインワンのMCPテスト開発ツール「OpenMCP」をオープンソース化しました。[全网第一个 MCP 服务器一体化开发测试软件 OpenMCP 发布!](https://zhuanlan.zhihu.com/p/1894785817186121106)
> OpenMCP QQグループ 782833642
OpenMCPオープンソースリンクhttps://github.com/LSTM-Kirigaya/openmcp-client
スターをお願いします :D
### 最初のMCPプロジェクト
前置きはこのくらいにして、コーディングを始めましょう :D
vscodeやtraeを開く前に、基本的なuvツールをインストールします。uvはコミュニティで人気のバージョン管理ツールで、性能の良いcondaと考えてください。
まずuvをインストールします。anacondaを使用している場合は、必ずbase環境に切り替えてからインストールしてください
```bash
pip install uv
```
インストールが完了したら、uvを実行します
```bash
uv
```
エラーがなければ成功です。uvは再利用不可能な依存関係のみをローカルにインストールするので、anacondaユーザーは心配ありません。uvがインストールするライブラリがbaseを汚染することはありません。次にuvを使用して基本的なPythonプロジェクトを作成します
```bash
mkdir simple-mcp && cd simple-mcp
uv init
uv add mcp "mcp[cli]"
```
次にvscodeまたはtraeを開き、プラグインストアでOpenMCPプラグインを探してダウンロードします
<div align=center>
<img src="https://picx.zhimg.com/80/v2-525c4576398078547fdd6eeef26532aa_1440w.png" style="width: 100%;"/>
</div>
まずMCPの最小プログラムを作成します
ファイル名simple_mcp.py
```python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP('錦恢の MCP Server', version="11.45.14")
@mcp.tool(
name='add',
description='对两个数字进行实数域的加法'
)
def add(a: int, b: int) -> int:
return a + b
@mcp.resource(
uri="greeting://{name}",
name='greeting',
description='用于演示的一个资源协议'
)
def get_greeting(name: str) -> str:
# 访问处理 greeting://{name} 资源访问协议,然后返回
# 此处方便起见,直接返回一个 Hellobalabala 了
return f"Hello, {name}!"
@mcp.prompt(
name='translate',
description='进行翻译的prompt'
)
def translate(message: str) -> str:
return f'请将下面的话语翻译成中文:\n\n{message}'
@mcp.tool(
name='weather',
description='获取指定城市的天气信息'
)
def get_weather(city: str) -> str:
"""模拟天气查询协议,返回格式化字符串"""
return f"Weather in {city}: Sunny, 25°C"
@mcp.resource(
uri="user://{user_id}",
name='user_profile',
description='获取用户基本信息'
)
def get_user_profile(user_id: str) -> dict:
"""模拟用户协议,返回字典数据"""
return {
"id": user_id,
"name": "张三",
"role": "developer"
}
@mcp.resource(
uri="book://{isbn}",
name='book_info',
description='通过ISBN查询书籍信息'
)
def get_book_info(isbn: str) -> dict:
"""模拟书籍协议,返回结构化数据"""
return {
"isbn": isbn,
"title": "Python编程从入门到实践",
"author": "Eric Matthes"
}
@mcp.prompt(
name='summarize',
description='生成文本摘要的提示词模板'
)
def summarize(text: str) -> str:
"""返回摘要生成提示词"""
return f"请用一句话总结以下内容:\n\n{text}"
```
実行してみます:
```bash
uv run mcp run simple_mcp.py
```
エラーがなく、止まっている場合は、依存関係のインストールに問題がないことを意味します。Ctrl+CまたはCtrl+Zで終了します。
これらの関数は単純で意味がないように見えるかもしれませんが、最終的なシステムに至るまでには簡単な例が必要です。
### リンク、スタート!
OpenMCPプラグインをダウンロードした場合、Pythonエディターの右上にOpenMCPの紫色のアイコンが表示されます。クリックするとOpenMCPが起動し、現在のMCPをデバッグできます。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-f67e000371095a755d2f0d613706d61c_1440w.png" style="width: 100%;"/>
</div>
デフォルトではSTDIOモードで起動し、以下のコマンドを実行します
```bash
uv run mcp run <現在開いているPythonファイルの相対パス>
```
したがって、mcpスキャフォールディング`uv add mcp "mcp[cli]"`)がインストールされていることを確認する必要があります。
開いたらまず左下の接続状態を確認し、緑色であることを確認します。これはOpenMCPとMCPサーバーが正常にハンドシェイクしたことを意味します。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-c4ebbbfe98d51e8b6e7de6c6d1bceb2e_1440w.png" style="width: 100%;"/>
</div>
接続に成功すると、接続の上に現在のMCPサーバーの名前が表示され、カーソルを合わせるとバージョン番号が表示されます。この情報は以下のコードで定義されています
```python
mcp = FastMCP('錦恢の MCP Server', version="11.45.14")
```
バージョン管理時に非常に便利です。このシステムを活用してください。
接続に失敗した場合は、左側のツールバーの2番目のボタンをクリックして接続コンソールに入り、エラー情報を確認するか、手動で接続コマンドを調整します
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-684190b98dbbb9a7bf0e8c8048bd1277_1440w.png" style="width: 100%;"/>
</div>
### OpenMCPの紹介
次に、OpenMCPの基本機能モジュールを簡単に紹介します。最初に画面に何も表示されていない場合は、上のプラス記号をクリックして新しいタブを作成します。このページには以下の4つのボタンが表示されます
<div align=center>
<img src="https://picx.zhimg.com/80/v2-3a4e8aa1ddaac632601532bb757a15ad_1440w.png?source=d16d100b" style="width: 100%;"/>
</div>
拡大:
<div align=center>
<img src="https://picx.zhimg.com/80/v2-ecc0705ed534e2cf0bc748ecd95f5f22_1440w.png" style="width: 100%;"/>
</div>
最初の3つリソース、プロンプト、ツールは、MCPの3つの対応する項目Resources、Prompts、Toolsをデバッグするために使用されます。これらの部分の使用法は基本的にMCP公式のInspectorツールと同じです。もちろん、私はこれらを参考にしました、えへ。
<div align=center>
<img src="https://pica.zhimg.com/80/v2-d767e782f667161442ea183f55ca49b1_1440w.png" style="width: 100%;"/>
</div>
4番目のボタン「インタラクティブテスト」は、私が開発したMCPクライアントで、基本的にはチャットウィンドウです。現在のMCPサーバーの機能関数をAIでシームレスにテストできます。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-b59ee2d290e096343fb4659baf34cf57_1440w.png" style="width: 100%;"/>
</div>
現在はツールのサポートのみを一時的に提供しています。プロンプトとリソースについてはまだ考えがまとまっていませんリソースはツールとして扱えると思います。グループで一緒に議論しましょうQQグループ 782833642
## 天気関数のデバッグを開始
### ツールのデバッグ
最初に示したMCPの例を覚えていますかOpenMCPを使用してこれらの関数を迅速にデバッグできます。今回の目標は天気予報MCPを作成することです。天気予報関数がすでに完成していると仮定し、それをツールとしてカプセル化します
```python
@mcp.tool(
name='weather',
description='获取指定城市的天气信息'
)
def get_weather(city: str) -> str:
"""模拟天气查询协议,返回格式化字符串"""
return f"Weather in {city}: Sunny, 25°C"
```
もちろん、今のところ意味はありません。黒龍江省の都市IDを入力しても25度と返しますが、これらの詳細は重要ではありません。まずはプロセス全体を体験し、トップダウンの理解を構築することがユーザーにとって学びやすいです。
この関数をデバッグする必要があります。OpenMCPを開き、新しい「ツール」デバッグプロジェクトを作成します
<div align=center>
<img src="https://picx.zhimg.com/80/v2-1c67ab54d67023e408413484768377cf_1440w.png" style="width: 100%;"/>
</div>
左側のリストにweatherツールが表示されます。選択し、右側の入力ボックスに何かを入力し、Enterまたは「実行」をクリックを押すと、以下の応答が表示されます
<div align=center>
<img src="https://picx.zhimg.com/80/v2-d32a9c0d9fcab497dc03152a72c4c62b_1440w.png" style="width: 100%;"/>
</div>
関数が返す文字列が表示され、問題なくリンクが機能していることがわかります。
### インタラクティブテスト
プログラミングは得意かもしれませんが、天気予報クローラーを素早く作成する前に、作成したツールをAIチャットに注入する方法を見てみましょう。AIを使用するには、まずAIプロバイダーと対応するAPIを選択する必要があります。左側のツールバーの3番目のボタンをクリックしてAPIモジュールに入り、使用するAIプロバイダーとモデルを選択し、APIトークンを入力して「保存」をクリックします
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-367780b204d2aa50354585272b71af20_1440w.png" style="width: 100%;"/>
</div>
新しいタブを作成し、「インタラクティブテスト」を選択します。これで直接AIとチャットできます。まずツールを注入しないAIが天気予報の質問にどのように応答するか見てみましょう。下部のツールバーの左から3番目のボタンをクリックしてツール選択インターフェースに入り、「すべてのツールを無効にする」を選択します
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-977a53ea14eae5e1a646fc73d379a422_1440w.png" style="width: 100%;"/>
</div>
「閉じる」をクリックした後、AIに質問します
```
杭州の気温は何度ですか?
```
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-d3aa56602f574a6968295f9a5c93438f_1440w.png" style="width: 100%;"/>
</div>
冒頭と同じ回答が返ってきました。非常に形式的で、実際には知らないからです。
ここで、「weather」ツールを単独で有効にします
<div align=center>
<img src="https://picx.zhimg.com/80/v2-2ed66eaff604d11d52f60201fca215d4_1440w.png" style="width: 100%;"/>
</div>
同じ質問をします:
<div align=center>
<img src="https://picx.zhimg.com/80/v2-e934d386e20b1de43fb5e0dd426de86e_1440w.png" style="width: 100%;"/>
</div>
25度という回答と追加の推論情報が返ってきました。
いくつかの詳細に注目しましょう。まず、AIは直接質問に答えず、weatherツールを呼び出します。呼び出しパラメータは
```json
{
"city": "杭州"
}
```
そして、MCPサーバーは以下の応答を返します
```
Weather in 杭州: Sunny, 25°C
```
最終的にAIはこの情報に基づいて回答を生成します。つまり、このプロセスでは実際に2回AIサービスを呼び出しています。また、2回の呼び出しの入力トークン数が非常に多いことがわかります。これはOpenMCPが関数呼び出しをJSONスキーマとしてリクエストパラメータに注入するためです。weatherツールのJSONスキーマは以下の図の右側のjsonのようになります
<div align=center>
<img src="https://picx.zhimg.com/80/v2-2ed66eaff604d11d52f60201fca215d4_1440w.png" style="width: 100%;"/>
</div>
OpenAIプロトコルをサポートするAIプロバイダーは、このような情報に対してfunction callingを行います。そのため、ツールを使用するAIリクエストの入力トークン数は多くなります。しかし、心配する必要はありません。ほとんどのプロバイダーはKVキャッシュを実装しており、同じプレフィックスの入力に対してキャッシュがあり、キャッシュヒット部分のコストは通常の入力出力トークン価格よりも大幅に低くなります。OpenMCPは各回答の下に、現在のリクエストの入力トークン、出力トークン、総トークン、キャッシュヒット率を示しています。
ここで:
- 「総トークン」=「入力トークン」+「出力トークン」
- 「キャッシュヒット率」=「キャッシュヒットトークン」/「入力トークン」
> はい、キャッシュヒット率は入力トークンの概念で、出力トークンにはキャッシュヒット率という概念はありません。
今後の開発では、この情報に基づいてサービスやプロンプトを最適化できます。
### 実際の天気予報を完成させましょう!
もちろん、このコードも非常に簡単で、直接AIに生成させることができます

View File

@ -1,309 +0,0 @@
# Pythonで天気情報MCPサーバーを実装
[今回のチュートリアル動画](https://www.bilibili.com/video/BV1zYGozgEHc)
## フック
さて、始める前に小さな例を見てみましょう。来週「アークナイツ」の「錆影新生」コスプレイベントに行く予定なので、土曜日の杭州の天気を知りたいと思い、AIに土曜日の天気を聞きました。するとAIは以下のような返答をしました
<div align=center>
<img src="https://picx.zhimg.com/80/v2-4c623ac6897e12093535b0d9ed9cf242_1440w.png" style="width: 100%;"/>
</div>
これは困ります。皆さんもよくあると思いますが、AIは「魚の釣り方を教える」ことが多く、時には単に最終結果を知りたいだけのとき、特に些細な日常の質問に対してはそう感じます。
実際、天気予報を実装するプログラムはたくさんあります。では、作成した天気予報プログラムをAIに接続し、実際の天気を教えてもらい、明日のコスプレイベントの服装を決める方法はないでしょうか
直接関数を書いてfunction callingを使うのは少し面倒です。AIプロバイダーのAPI呼び出しやタスクループの構築、テキストレンダリングなど、多くの技術的な詳細を検討する必要があり、貴重な時間を浪費します。MCPは私たちに救いの道を与えてくれました。今回のチュートリアルでは、簡単なMCPサーバーを作成し、AIに天気予報を知る能力を与える方法を教えます。
## はじめに
👉 [前回のナビゲーション](https://zhuanlan.zhihu.com/p/32593727614)
前回はMCPの基礎を簡単に説明しました。今回は、独自のMCPサーバーの開発を開始し、既存のアプリケーション、サービス、ハードウェアなどをAIに接続します。これにより、AIからエンドユーザーアプリケーションへの最後の1キロメートルを完了します。
「工欲善其事、必先利其器」。よりエレガントで楽しいMCPサーバー開発のために、開発プロセスでプログラムの変更を確認し、直接AIに接続してツールの有効性を検証できる優れたテストツールが必要です。
そこで、私は最近、統合型MCPテスト開発ツール「OpenMCP」をオープンソース化しました。[初のMCPサーバー統合開発テストソフトウェアOpenMCPリリース](https://zhuanlan.zhihu.com/p/1894785817186121106)
> OpenMCP QQグループ 782833642
OpenMCPオープンソースリンクhttps://github.com/LSTM-Kirigaya/openmcp-client
スターをお願いします :D
### 最初のMCPプロジェクト
前置きはこのくらいにして、コーディングを始めましょう :D
vscodeやtraeを開く前に、基本的なuvツールをインストールします。uvはコミュニティで人気のバージョン管理ツールで、性能の良いcondaと理解してください。
まずuvをインストールします。anacondaを使用している場合は、必ずbase環境に切り替えてからインストールしてください
```bash
pip install uv
```
インストールが完了したら、uvを実行します
```bash
uv
```
エラーがなければ成功です。uvは再利用不可能な依存関係のみをローカルにインストールするため、anacondaを使用している方は心配ありません。uvがインストールするライブラリがbaseを汚染することはありません。次に、uvを使用して基本的なpythonプロジェクトを作成します
```bash
mkdir simple-mcp && cd simple-mcp
uv init
uv add mcp "mcp[cli]"
```
次にvscodeまたはtraeを開き、プラグイン市場でOpenMCPプラグインを探してダウンロードします
<div align=center>
<img src="https://picx.zhimg.com/80/v2-525c4576398078547fdd6eeef26532aa_1440w.png" style="width: 100%;"/>
</div>
まずMCPの最小プログラムを作成します
ファイル名simple_mcp.py
```python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP('錦恢の MCP Server', version="11.45.14")
@mcp.tool(
name='add',
description='2つの数値の実数領域での加算'
)
def add(a: int, b: int) -> int:
return a + b
@mcp.resource(
uri="greeting://{name}",
name='greeting',
description='デモンストレーション用のリソースプロトコル'
)
def get_greeting(name: str) -> str:
# greeting://{name}リソースアクセスプロトコルを処理し、返す
# ここでは簡単のため、直接Helloを返す
return f"Hello, {name}!"
@mcp.prompt(
name='translate',
description='翻訳用のプロンプト'
)
def translate(message: str) -> str:
return f'以下の文章を中国語に翻訳してください:\n\n{message}'
@mcp.tool(
name='weather',
description='指定都市の天気情報を取得'
)
def get_weather(city: str) -> str:
"""天気予報プロトコルをシミュレートし、フォーマットされた文字列を返す"""
return f"Weather in {city}: Sunny, 25°C"
@mcp.resource(
uri="user://{user_id}",
name='user_profile',
description='ユーザー基本情報を取得'
)
def get_user_profile(user_id: str) -> dict:
"""ユーザープロトコルをシミュレートし、辞書データを返す"""
return {
"id": user_id,
"name": "張三",
"role": "developer"
}
@mcp.resource(
uri="book://{isbn}",
name='book_info',
description='ISBNで書籍情報を検索'
)
def get_book_info(isbn: str) -> dict:
"""書籍プロトコルをシミュレートし、構造化データを返す"""
return {
"isbn": isbn,
"title": "Pythonプログラミング入門から実践まで",
"author": "Eric Matthes"
}
@mcp.prompt(
name='summarize',
description='テキスト要約のプロンプトテンプレート'
)
def summarize(text: str) -> str:
"""要約生成プロンプトを返す"""
return f"以下の内容を一言で要約してください:\n\n{text}"
```
実行してみます:
```bash
uv run mcp run simple_mcp.py
```
エラーがなく、止まっている場合は、依存関係のインストールに問題がないことを意味します。ctrl cまたはctrl zで終了してください。
これらの関数は単純で意味がないように見えるかもしれませんが、最終的なシステムに到達するためには、簡単な例が必要です。
### リンク、スタート!
OpenMCPプラグインをダウンロードした場合、pythonエディタの右上にOpenMCPの紫色のアイコンが表示されます。クリックするとOpenMCPが起動し、現在のMCPをデバッグできます。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-f67e000371095a755d2f0d613706d61c_1440w.png" style="width: 100%;"/>
</div>
デフォルトではSTDIOモードで起動し、以下のコマンドを実行します
```bash
uv run mcp run <現在開いているpythonファイルの相対パス>
```
したがって、mcpスキャフォールド`uv add mcp "mcp[cli]"`)がインストールされていることを確認してください。
開いたらまず左下の接続状態を確認し、緑色であることを確認します。これはOpenMCPとMCPサーバーが正常にハンドシェイクしたことを示します。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-c4ebbbfe98d51e8b6e7de6c6d1bceb2e_1440w.png" style="width: 100%;"/>
</div>
接続に成功すると、接続の上に現在のMCPサーバーの名前が表示され、カーソルを合わせるとバージョン番号が表示されます。この情報は以下のコードで定義されます
```python
mcp = FastMCP('錦恢の MCP Server', version="11.45.14")
```
これはバージョン管理時に非常に便利です。このシステムを活用してください。
接続に失敗した場合は、左側のツールバーの2番目のボタンをクリックして接続コンソールに入り、エラーメッセージを確認するか、手動で接続コマンドを調整します
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-684190b98dbbb9a7bf0e8c8048bd1277_1440w.png" style="width: 100%;"/>
</div>
### OpenMCPの紹介
次に、OpenMCPの基本機能モジュールを簡単に紹介します。最初に画面に何も表示されていない場合は、上のプラス記号をクリックして新しいタブを作成します。このページには以下の4つのボタンが表示されます
<div align=center>
<img src="https://picx.zhimg.com/80/v2-3a4e8aa1ddaac632601532bb757a15ad_1440w.png?source=d16d100b" style="width: 100%;"/>
</div>
拡大:
<div align=center>
<img src="https://picx.zhimg.com/80/v2-ecc0705ed534e2cf0bc748ecd95f5f22_1440w.png" style="width: 100%;"/>
</div>
最初の3つ、リソース、プロンプト、ツールは、MCP内の対応する項目Resources、Prompts、Toolsをデバッグするために使用されます。これらの部分の使用法は基本的にMCP公式のInspectorツールと同じです。もちろん、私はこれらを参考にしました。
<div align=center>
<img src="https://pica.zhimg.com/80/v2-d767e782f667161442ea183f55ca49b1_1440w.png" style="width: 100%;"/>
</div>
4番目のボタン「インタラクティブテスト」は、私が開発したMCPクライアントで、基本的にはダイアログウィンドウです。現在のMCPサーバーの機能関数をAIで直接テストできます。
<div align=center>
<img src="https://picx.zhimg.com/80/v2-b59ee2d290e096343fb4659baf34cf57_1440w.png" style="width: 100%;"/>
</div>
現在はツールのサポートのみを提供しています。プロンプトとリソースについてはまだ考えがまとまっていませんリソースはツールとして扱えると思います。グループで一緒に議論しましょうQQグループ 782833642
## 天気関数のデバッグを開始
### ツールデバッグ
最初に示したMCPの例を覚えていますかOpenMCPを使用して、これらの関数を迅速にデバッグできます。今回の目標は、天気予報MCPを作成することです。天気予報関数がすでに作成されていると仮定し、それをツールとしてカプセル化します
```python
@mcp.tool(
name='weather',
description='指定都市の天気情報を取得'
)
def get_weather(city: str) -> str:
"""天気予報プロトコルをシミュレートし、フォーマットされた文字列を返す"""
return f"Weather in {city}: Sunny, 25°C"
```
もちろん、今のところ意味はありません。黒龍江省の都市IDを入力しても25度を返しますが、これは重要ではありません。まず全体のプロセスを理解することが重要です。詳細にこだわるよりも、トップダウンで感覚的な理解を構築する方がユーザーにとって学びやすいです。
この関数をデバッグするには、OpenMCPを開き、新しい「ツール」デバッグプロジェクトを作成します
<div align=center>
<img src="https://picx.zhimg.com/80/v2-1c67ab54d67023e408413484768377cf_1440w.png" style="width: 100%;"/>
</div>
左側のリストにweatherツールが表示されます。それを選択し、右側の入力ボックスに何かを入力してEnterまたは「実行」をクリックを押すと、以下の応答が表示されます
<div align=center>
<img src="https://picx.zhimg.com/80/v2-d32a9c0d9fcab497dc03152a72c4c62b_1440w.png" style="width: 100%;"/>
</div>
関数が返す文字列が表示され、問題なくリンクが機能していることがわかります。
### インタラクティブテスト
プログラミングは得意かもしれませんが、天気予報クローラーを素早く作成する前に、作成したツールをAIダイアログに注入する方法を見てみましょう。AIを使用するには、まずAIモデルと対応するAPIを選択する必要があります。左側のツールバーの3番目のボタンをクリックしてAPIモジュールに入り、使用するAIモデルプロバイダー、モデルを選択し、APIトークンを入力して「保存」をクリックします
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-367780b204d2aa50354585272b71af20_1440w.png" style="width: 100%;"/>
</div>
新しいタブを作成し、「インタラクティブテスト」を選択します。これで直接AIと対話できます。まずツールを注入せずにAIが天気予報の質問にどのように応答するかを見てみましょう。下部のツールバーの左から3番目のボタンをクリックしてツール選択インターフェースに入り、「すべてのツールを無効にする」を選択します
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-977a53ea14eae5e1a646fc73d379a422_1440w.png" style="width: 100%;"/>
</div>
「閉じる」をクリックした後、AIに質問します
```
杭州の気温は何度ですか?
```
<div align=center>
<img src="https://pic1.zhimg.com/80/v2-d3aa56602f574a6968295f9a5c93438f_1440w.png" style="width: 100%;"/>
</div>
AIは記事の冒頭と同じ回答をしました。非常に形式的で、実際には知らないからです。
ここで、「weather」ツールを個別に有効にします
<div align=center>
<img src="https://picx.zhimg.com/80/v2-2ed66eaff604d11d52f60201fca215d4_1440w.png" style="width: 100%;"/>
</div>
同じ質問をします:
<div align=center>
<img src="https://picx.zhimg.com/80/v2-e934d386e20b1de43fb5e0dd426de86e_1440w.png" style="width: 100%;"/>
</div>
AIは25度と回答し、追加の推論情報も提供しました。
いくつかの詳細に注目しましょう。まず、AIは直接質問に答えず、weatherツールを呼び出します。呼び出しパラメータは
```json
{
"city": "杭州"
}
```
そして、MCPサーバーは以下の応答を返します
```
Weather in 杭州: Sunny, 25°C
```
これに基づいて、AIは最終的な回答を提供します。つまり、このプロセスでは実際に2回AIサービスを呼び出しています。また、2回の呼び出しの入力トークン数が非常に多いことがわかります。これはOpenMCPが関数呼び出しをJSONスキーマ形式でリクエストパラメータに注入するためです。weatherツールのJSONスキーマは以下の図の右側のjsonのようになります
<div align=center>
<img src="https://picx.zhimg.com/80/v2-2ed66eaff604d11d52f60201fca215d4_1440w.png" style="width: 100%;"/>
</div>
openaiプロトコルをサポートするAIプロバイダーは、このような情報に対してfunction callingを実行します。そのため、ツールを使用するAIリクエストの入力トークン数は大きくなります。ただし、心配する必要はありません。ほとんどのプロバイダーはKVキャッシュを実装しており、同じプレフィックスの入力に対してキャッシュがあり、キャッシュヒット部分のコストは通常の入力出力トークン価格よりも大幅に低くなります。OpenMCPは各回答の下に、現在のリクエストの

View File

@ -1,27 +0,0 @@
---
layout: doc
---
# よくある質問
## エラーコード説明
### 32000 - MCP接続失敗
MCP接続失敗の原因は複数考えられます。以下に一般的なケースを挙げます
• **仮想環境パスの不一致**
仮想環境venvとエントリーファイルのパスが一致していない場合、接続失敗の原因となることがあります。
詳細な解決方法はこちら:[設定説明](./venv-not-same-path/venv-not-same-path.md)
---
• **その他の可能性**
- ポートが使用中
- 環境変数の設定誤り
- 依存ライブラリが正しくインストールされていない
> 上記の問題が発生した場合、まずエラーログで詳細を確認してください。問題が解決しない場合は、[GitHub Issues](https://github.com/LSTM-Kirigaya/openmcp-client/issues)でサポートを求めてください。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,29 +0,0 @@
# 仮想環境とエントリーファイルが異なるディレクトリにある場合の設定方法
## 問題の説明
OpenMCPを使用する際、仮想環境venvとPythonファイルが同じディレクトリにない場合があり、仮想環境がプロジェクトフォルダの外にあることもあります。このような場合、右上の接続ボタンをクリックするとMCP接続失敗エラーコード32000が発生する可能性があります。
## 解決策
### 1. 実行ディレクトリの調整
接続オプションで、実行ディレクトリを仮想環境がある場所に調整する必要があります:
![MCP接続オプション画面](./image-2.png)
### 2. 実行コマンドの変更
同時に、実行コマンドを適切に変更する必要があります:
![実行コマンド変更例](./image.png)
### 3. インタプリタパスの直接指定
特定の場合には、コマンドでPythonインタプリタのフルパスを直接指定できます。例
```bash
C:\code\ygo-chat\.venv\Scripts\python.exe example.py
```
> 注意この方法はnodeやmcp指令の【コマンド】、その他のmcp clientのmcp設定ファイルにも適用できます。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 KiB

View File

@ -1,43 +0,0 @@
---
next:
text: MCPとは
link: '/plugin-tutorial/what-is-mcp'
---
# OpenMCP 概要
:::warning
OpenMCPの学習を開始する前に、MCPの基本概念を理解することを強くお勧めします[エージェント時代のインフラストラクチャ | MCPプロトコル紹介](https://kirigaya.cn/blog/article?seq=299)
:::
## OpenMCPとは
OpenMCPは開発者向けのMCPデバッガーおよびSDKであり、AI Agentの全リンク開発コストと開発者の認知的負荷を軽減することを目的としています。
![](./images/openmcp.png)
OpenMCPは2つの部分に分かれていますが、このセクションではOpenMCPデバッガーの部分の使用方法について説明します。この部分はOpenMCP Clientとも呼ばれています。OpenMCP Clientの本体は、vscodeのようなエディタ上で動作するプラグインです。現在のMCPプロトコルのすべての機能と互換性があり、開発者にとって便利な豊富な機能を提供しており、Claude Inspectorの上位互換として使用できます。
:::info vscodeのようなエディタ (VLE)
vscodeのようなエディタvscode-like editor、略称VLEとは、Vscodiumカーネルをベースに開発された汎用コードエディタのことで、大部分のvscodeプラグインエコシステムと互換性があり、vscodeと同様の機能LSP3.7プロトコルのサポート、remote sshによるリモート開発機能、エディター間で設定ファイルを共有する機能などを備えています。
代表的なVLEには、vscode、trae、cursor、およびvscodiumの各種ディストリビューションがあります。
:::
## Claude Inspectorとは
Claude Inspectorは、Claude公式つまりMCPプロトコルの提案者がリリースしたオープンソースのMCPデバッガーです。開発者はMCPサーバーの開発後に、このデバッガーを使用して機能の完全性をテストできます。
![](./images/inspector.png)
ただし、Inspectorツールには以下のような欠点があります
- 使用が面倒Inspectorを使用するたびに、mcp devでWebフロントエンドとバックエンドのアプリケーションを起動する必要があります。
- 機能が少ないInspectorは最も基本的なMCPのtool属性などのデバッグのみを提供しています。ユーザーが開発したMCPサーバーが大規模モデルとの相互作用でどのように動作するかをテストしたい場合、Claude Desktopに接続してクライアントを再起動する必要があり、連続的なデバッグシナリオでは非常に不便です。
- いくつかのバグが存在SSEやstreamable httpなどのリモート接続シナリオでは、Inspectorに既知のバグがあり、実際の産業レベルの開発に大きな影響を与えています。
- デバッグ内容を保存または記録できない大規模なマイクロサービスMCP化プロジェクトでは、これは非常に重要です。
- 複数のMCPサーバーを同時にデバッグできないMCPの原子化水平展開シナリオでは、これは必要な機能です。
OpenMCP Clientが作成された理由の1つは、Inspectorの上記の課題を解決し、MCPサーバーの開発ハードルを下げ、ユーザーがビジネス自体に集中できるようにすることです。
<!-- -->

View File

@ -1,60 +0,0 @@
---
layout: doc
---
# OpenMCPの入手方法
## プラグインストアからOpenMCPをインストール
主要なVLEのプラグインストアで直接OpenMCPプラグインを入手できます。例えばVSCodeでは、左側のプラグインストアをクリックし、検索ボックスに`OpenMCP`と入力するとOpenMCPプラグインが見つかります。
![vscode プラグインストア](./images/vscode-plugin-market.png)
## オフラインインストール
VLEのプラグインは本質的にzip圧縮ファイルであり、拡張子はvsixで全プラットフォーム共通です。私たちのCI/CDボットは各バージョンリリース後に自動的にビルドし、vsixをGitHub Releaseにアップロードします。以下のリンクから対応バージョンのGitHub Releaseページにアクセスできます:
```
https://github.com/LSTM-Kirigaya/openmcp-client/releases/tag/v{バージョン番号}
```
例えばバージョン0.1.1の場合、リリースページのリンクはこちらです: [https://github.com/LSTM-Kirigaya/openmcp-client/releases/tag/v0.1.1](https://github.com/LSTM-Kirigaya/openmcp-client/releases/tag/v0.1.1)
`Assets`の下に対応するvsix圧縮ファイルがあります
![github release](./images/github-release.png)
その他にも、以下のストアウェブサイトから最新のopenmcpのvsixを入手できます
- https://open-vsx.org/extension/kirigaya/openmcp
- https://marketplace.visualstudio.com/items?itemName=kirigaya.openmcp
vsix拡張子のファイルをクリックしてダウンロードし、ダウンロードが完了したら直接インストールできます。VLEで外部のvsixファイルをインストールする方法は2つあります。
### 方法1: VLE内でインストール
VLEのプラグインストアページには3点リーダーボタンがあり、クリックすると以下のリスト内の赤くマークされたボタンが表示されます
![vscode プラグインストア](./images/vscode-plugin-market-install-from.png)
クリック後、先ほどダウンロードしたvsixファイルを見つけ、クリックするとインストールが完了します。
### 方法2: コマンドラインを使用
VLEがグローバルにインストールされている場合、自動的にコマンドラインツールが利用可能になります。コマンドは以下の通りです:
::: code-group
```bash [vscode]
code --install-extension /path/to/openmcp-0.1.1.vsix
```
```bash [trae]
trae --install-extension /path/to/openmcp-0.1.1.vsix
```
```bash [cursor]
cursor --install-extension /path/to/openmcp-0.1.1.vsix
```
:::
`/path/to/openmcp-0.1.1.vsix`はダウンロードしたvsixファイルの絶対パスを表します。これでもプラグインをインストールできます。

View File

@ -1,136 +0,0 @@
# あなたの最初のMCP
MCPを実装するプログラミング言語は多く、一般的なほぼすべてのプログラミング言語に公式・非公式のサポートがあります。「プログラミング言語 + MCP」で検索すれば対応するライブラリが見つかります。[[mcp-examples|MCPサーバー開発事例]]では、さまざまなプログラミング言語の異なる例も提供しています。
すべてのプログラミング言語の中で、PythonでのMCP開発は間違いなく最も簡単で、初心者にも取り組みやすいものです。そのため、最初のMCPはPythonで実装します。他のプログラミング言語での実装も大同小異です。
## uvのインストール
Pythonでmcpサーバーを書く際には、パッケージマネージャーとしてuvを使用することを強く推奨します。uvについて知っておくべきことは、高性能なパッケージマネージャーであり、pipとcondaのすべての利点を備えていることです。uvがインストールされていない場合は、まずpipでuvをインストールしてください
```bash
pip install uv
```
:::warning anacondaまたはminicondaを使用している方へ
非base環境にuvをインストールしないでください。base環境でuvをインストールしてください。uv自体が環境の分離を適切に行いますので、uvがbase環境を汚染する心配はありません。base環境以外にインストールしたり、グローバルなpipでインストールしたりすると、uvがどこにインストールされたのかわからなくなりますbase環境でpipを使用してインストールしたスクリプトは`~/anaconda/bin/uv`にインストールされますので、`~/anaconda/bin/``$PATH`に含まれていることも確認してください。
:::
uvのバージョンを確認します
```bash
uv version
```
私の出力は次の通りです:
```
uv 0.6.9 (3d9460278 2025-03-20)
```
実際に操作する際には、このバージョンよりも低くならないようにしてください。
## 最もシンプルなmcpサーバーの作成
プロジェクトディレクトリに移動し、最もシンプルなmcpサーバーを作成する準備をします。
```bash
mkdir -p ~/codes/my-first-mcp
cd ~/codes/my-first-mcp
uv init --no-workspace
```
この時点で、プロジェクト内には以下の3つのファイルがあるはずです
```
README.md main.py pyproject.toml
```
次に、現在のフォルダでvscodeまたはtraeを開き、最もシンプルなmcpサーバーを作成します。その機能は次の通りです
- 2つの数字を加算するための「add」というツールを提供
- 挨拶メッセージを返す「greeting」というリソースを提供
まず、mcp関連のライブラリをインストールします
```bash
uv add mcp "mcp[cli]"
```
`main.py`の内容を以下のように変更します:
```python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP('錦恢の MCP Server', version="11.45.14")
@mcp.tool(
name='add',
description='2つの数字を実数領域で加算する'
)
def add(a: int, b: int) -> int:
return a + b
@mcp.resource(
uri="greeting://{name}",
name='greeting',
description='デモンストレーション用のリソースプロトコル'
)
def get_greeting(name: str) -> str:
return f"Hello, {name}!"
@mcp.prompt(
name='translate',
description='翻訳を行うプロンプト'
)
def translate(message: str) -> str:
return f'以下の文章を中国語に翻訳してください:\n\n{message}'
```
## OpenMCPでワンクリック接続
上記のように、mcpのtool、resource、promptとして使用する3つの関数を宣言しました。OpenMCPでこれらを起動するのは非常に簡単で、右上のOpenMCPアイコンをクリックするだけで接続できます
![](./images/connect-simple.png)
OpenMCPを初めて使用する場合、ガイド画面が表示されますので、ぜひ最後までご覧ください。
![](./images/guide.png)
ログインが完了し、以下のように接続成功と表示されれば、mcpサーバーの起動と接続が成功したことを意味します。
![](./images/connect-success.png)
おめでとうございます。最初の一歩が最も難しいですが、あなたはすでに最も難しいmcp接続を完了しました
OpenMCPを使用したmcpサーバー接続に関する詳細情報は、マニュアルのこの章[[connect-mcp|MCPサーバーへの接続]]を参照してください。
## 付録uvでmcpを起動する際に知っておくべきこと
OpenMCPはすでに多くのことを行ってくれていますが、uvでmcpサーバーを起動する方法は1つだけではありません。より基本的な原理を理解することで、あらゆる状況に対応できるようになります。OpenMCPはPythonプロジェクトに対してデフォルトで`uv run mcp run main.py`を実行してmcpサーバーを起動しますが、GitHub上の一部のプロジェクトはこの方法では起動できません。
まず、上記の例のPythonコードをコマンドラインからどのように起動するかを理解しましょう
### 方法1mcp-cliを使用する
mcp自体がスキャフォールディングを提供しており、宣言されたPythonコードを直接起動してmcpサーバーとして実行できます。以下のコードで実行します
```bash
uv run mcp run main.py
```
### 方法2コード内で明示的に起動する
コード内で明示的にmcpサーバーを起動することもできます。`main.py`の末尾に以下を追加します:
```python
if __name__ == '__main__':
mcp.run()
```
その後、以下のコードを実行すればmcpサーバーが起動します
```bash
uv run main.py
```
:::warning
`python main.py`を実行しないでください。`uv run`は現在の仮想環境のライブラリを使用しますが、これらのライブラリは外部のPythonからは見えません。また、`mcp.run()`で起動コードを使用せずに`uv run main.py`を直接使用することも避けてください。私たちがこれまでに書いたコードは関数を宣言しただけで、実際には何の機能も実行していません。
:::

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 466 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 KiB

View File

@ -1,11 +0,0 @@
# クイックスタート
1. [[acquire-openmcp|OpenMCPを入手する]]
2. [[first-mcp|最初のMCPを作成]]
3. [[quick-debug|MCPを迅速にデバッグ]]
4. [[put-into-llm|大規模言語モデルでテストしてみよう!]]
<br>
<br>

View File

@ -1,63 +0,0 @@
# 大モデルで性能をテストしよう!
[[quick-debug|前章]]では、mcpサーバーへの接続と各機能のデバッグを無事完了し、openmcpの基本的なデバッグ機能を紹介しました。次は、mcpを大規模モデル環境でテストする段階です。そもそもmcpが提案された目的は、誰もが自分で書いた機能を低コストで大規模モデルに統合できるようにするためでした。
本格的な対話を始める前に、[[connect-llm|大モデル接続]]を参照して大モデルAPIの設定を完了し、あなたの大モデルサービスが利用可能かどうかテストしてください。
## 大モデルとの対話
新しいデバッグプロジェクトを作成し、「インタラクティブテスト」を選択すると、大モデルとの対話ウィンドウが開きます。OpenMCPが提供する対話ウィンドウの基本構成は以下の通りです
![](./images/llm-intro.png)
重要なボタンがいくつか表示されています。初めて使用する際は、デフォルト設定のまま進めても構いません。「使用するツール」をクリックすると、現在有効なツールが表示されます。OpenMCPはデフォルトで接続されているmcpサーバーが提供する全てのツールを有効にします。特定のツールを無効にしたい場合は、「使用するツール」から選択的に無効化できます
![](./images/llm-tools.png)
それでは、mcpプロトコルに基づいて大モデルがどのようにツールを呼び出すか見てみましょう。デフォルト設定のまま、次の質問を入力します<mark>123 + 1313 の計算結果を教えてください</mark>
入力後、Enterキーを押して結果を待つと、以下のような出力が得られます
![](./images/llm-calc.png)
大モデルが提供されたaddツールを使用して加算を実行したことがわかります。OpenMCPでは、大モデルが各ツールをどのように呼び出し、ツールからどのような結果が返されたかを確認できます。現在の質問とmcpが提供するツールは比較的単純ですが、複雑な問題の場合、大モデルは1回の応答で複数のツールを同時に呼び出して特定のタスクを完了することがあります。大モデルに毎回1つのツールのみを使用させたい場合は、デフォルトで点灯している「モデルが単一応答で複数ツールを呼び出すことを許可」をクリックしてこの機能を無効にできます。
## システムプロンプト
[bing-images](/Users/bytedance/projects/openmcp-tutorial/bing-images)のような特殊なケースでは、キーワードに基づいてbingの画像を返すmcpサーバーです。
次の質問を直接投げかけてみましょう:<mark>アークナイツの画像をいくつか検索してください</mark>。デフォルト設定では、以下のような応答が得られる可能性があります:
![](./images/bing-image-common.png)
大モデルは取得した画像をリンク形式で返しましたが、時には画像形式で画面にレンダリングして表示してほしい場合もあります。大モデルの応答スタイルを制約・誘導したり、要求したテンプレートに従って応答させるためには、システムプロンプトを設定することで実現できます。
まず、下部の「システムプロンプト」をクリックします:
![](./images/system-prompt-add.png)
新しいシステムプロンプトを追加し、タイトルに「bing image」と入力し、本文に以下を記入します
```
あなたはbing画像検索が得意なAIです。画像を見つけたら、markdown形式で画像を返す必要があります。例えば ![](https://xxxx.xx/xxxx)
```
保存をクリックします。
![](./images/system-prompt-image.png)
次に、最初のユーザーダイアログにカーソルを移動させると、いくつかのボタンが表示されます。再実行ボタンを選択すると、openmcpはこの対話を再実行します。
![](./images/rerun-bing-image.png)
すると、画像が正常にレンダリングされていることが確認できます:
![](./images/llm-bing-image-render.png)
system promptやその他のより精密な方法でagentを制御するテクニックについてさらに学びたい場合は、[[go-neo4j-sse|goで実装するneo4jの読み取り専用mcpサーバー (SSE)]]を参照してください。
## まとめ
おめでとうございますopenmcpの基本チュートリアルを完了しました。次は、何か面白いことに取り組む時です[[mcp-examples|MCPサーバー開発事例]]では、openmcpを使用したmcpサーバー開発のさらなる例を見つけることができます。
様々な驚きがあなたをお待ちしています。どうぞご自由にお取りください。

View File

@ -1,48 +0,0 @@
# MCPの迅速なデバッグ
[[first-mcp|最初のMCP]]では、MCPサーバーの最小インスタンスを作成し、openmcpを使ってこのサーバーに接続することに成功しました。
次に、このサーバーの機能をデバッグできます。結局のところ、Jeaf Deanのように誰もが一度で全てのコードを正しく書けるわけではありません。私たちが作成するMCPサーバーも、最初から自信を持って公開できるものばかりではなく、常に私たちが気付かない問題が存在します。想像してみてください、後でmcpを大規模モデルに接続して全リンクのデバッグを行う際に問題が発生した場合、その時には非常に多くのエラー要因が考えられることに気付くでしょうMCPサーバーの問題大規模モデルベンダーの問題OpenMCPの問題可能性のあるエラーを分類し、一つずつ調査することが、エンジニアリングの直感(Engineering Instuition)に適った方法です。
## パネルの理解
初めてopenmcpに入ると、パネルが表示され、4つのボタンがあり、4種類のデバッグ項目を表しています
![](./images/openmcp-home.png)
私たちが現在確認する必要があるのは、tool、resource、promptの3つの機能が正常に動作しているかどうかです。実際のプロジェクトでは、toolが最も頻繁に使用される項目であるため、まずtoolをデバッグします。
## Toolのデバッグ
toolをデバッグするために、パネルの「ツール」ボタンをクリックし、toolデバッグインターフェースに入ります。toolパネルの基本説明は以下の通りです
![](./images/tool-desc.png)
ツールをデバッグするには、まず「ツールリスト」からツールを選択する必要があります(展開されていない場合はまずツールリストを展開し、右側のボタンをクリックして更新できます)。次に、右側の「パラメータ入力と実行」でテストするパラメータを入力し、実行をクリックすると結果が表示されます:
![](./images/tool-result.png)
例えば、ここで最も簡単な2 + 2を計算すると、結果は4であることがわかります。これは、私たちのmcp接続が正常で、正しく結果を返すことができることを示しています。将来的には、簡単なテストを通じてmcpサーバーの可用性を検証できます。これは複雑なagentシステムのデバッグプロセスにおいて非常に重要です。自己診断プログラムの一部としてコード化することも可能です。
## テスト項目の追加
1つの項目のテストが完了したら、上部の+をクリックして追加のテスト項目を追加できます:
![](./images/tool-add-test-project.png)
ここでは、「リソース」を選択してリソース項目のデバッグ作業を行います。「リソース」は他の2つの項目とは少し異なり、MCPプロトコルにおけるリソースアクセスには2つのタイプがあります
- resources/templates/list: テンプレートリソース。アクセスパラメータを持ちます。例えば、ファイルシステムmcp内のファイルアクセスで、ファイルパスを入力し、リソースプロトコルに従ってファイル内容を返します。
- resources/list通常のリソース。アクセスパラメータを持ちません。例えば、ブラウザmcp内のconsoleで、直接コンソールのstdioを返します。この場合、パラメータは必要ありません。
![](./images/resource-desc.png)
`resources/templates/list`の使用方法は以前のtoolと同じで、パラメータを入力して実行をクリックするとリソース結果が表示されます
![](./images/resource-result.png)
一方、`resources/list`はパラメータがないため、左側のリソースを直接クリックするだけで内部データを確認できます。
## まとめ
この章では、主にopenmcpを使用してMCPサーバーをデバッグする方法を紹介しました。toolとresourceのデバッグ方法を含み、promptの方法もこれらと似ていますので、各自で試してみてください。次の章では、最もエキサイティングな章を開始します。開発したmcpサーバーを大規模モデルに投入してテストを行い、作成したmcpが本当に面白く、価値があるかどうかを確認します。

View File

@ -1,66 +0,0 @@
# 大モデルの接続
「インタラクションテスト」を使用して大モデルとの対話中にMCPツールの性能をテストする場合、まずOpenMCPで大モデルを設定する必要があります。
:::warning プロトコル互換性に関する警告
現在OpenMCPはOpenAIインターフェース仕様に準拠した大モデルサービスのみをサポートしています。他の大モデルを呼び出す必要がある場合は、[newApi](https://github.com/QuantumNous/new-api)を介して転送するか、独自に実装してください。
現在市場で主流の以下のモデルはすべてサポートしています。大モデルの接続に問題が発生した場合は、いつでも[[channel|お問い合わせください]]。
:::
「設定」-「API」で大モデルの接続設定画面に入ることができます。
![](./images/setting-api.png)
## デフォルトでサポートされているモデル
OpenMCPはデフォルトで市場で一般的な大モデルを事前に設定しています。以下はサポートされているモデルです。
| 大モデル名 | プロバイダー | baseUrl | デフォルトモデル |
|----------------------|-----------------------------|---------------------------------------------|-----------------------|
| DeepSeek | DeepSeek | `https://api.deepseek.com/v1` | `deepseek-chat` |
| OpenAI | OpenAI | `https://api.openai.com/v1` | `gpt-4-turbo` |
| 通義千問 Qwen | Alibaba | `https://dashscope.aliyuncs.com/compatible-mode/v1` | `qwen-plus` |
| 豆包 Seed | ByteDance | `https://ark.cn-beijing.volces.com/api/v3` | `doubao-1.5-pro-32k` |
| Gemini | Google | `https://generativelanguage.googleapis.com/v1beta/openai/` | `gemini-2.0-flash` |
| Grok | xAI | `https://api.x.ai/v1` | `grok-3-mini` |
| Mistral | Mistral AI | `https://api.mistral.ai/v1` | `mistral-tiny` |
| Groq | Groq | `https://api.groq.com/openai/v1` | `mixtral-8x7b-32768` |
| Perplexity | Perplexity AI | `https://api.perplexity.ai/v1` | `pplx-7b-online` |
| Kimi Chat | 月の暗面 (Moonshot AI) | `https://api.moonshot.cn/v1` | `moonshot-v1-8k` |
## 大モデルの設定
対応するサービスプロバイダーのapiTokenをopenmcpに入力するだけです。その後「テスト」をクリックし、以下の応答が表示されれば接続成功です。インタラクションテストで大モデルを使用できるようになります
![](./images/setting-api-test.png)
:::warning
一部のユーザーはアクセスできない問題に遭遇する可能性があります。baseUrlが正しく入力されていることを確認してください。国内でGeminiやOpenAIなどの国外プロバイダーのサービスを使用する場合、ネットワーク環境がこれらのサービスにアクセスできることを確認してください。「設定」-「一般」でプロキシサーバーを設定できます。
:::
## モデルの追加
使用したい特定のプロバイダーのモデルがデフォルトでサポートされていない場合、2つの方法で追加できます。
### 方法1モデルリストの更新
ここでは通義千問を例にします。apitokenが正しく入力されていることを確認した上で、「モデルリストを更新」をクリックします。プロバイダーがOpenAI標準を厳密に実装していれば、すべての更新されたモデルが表示されます。
![](./images/setting-update-models.png)
### 方法2手動でのモデル追加
サーバーがOpenAI標準をサポートしていない場合、「方法1」を使用できません。このように手動でモデルリストを追加できます。ここではGrokを例にします。プロバイダーリストからgrokを探し、図に示す編集をクリックします。
![](./images/setting-api-edit.png)
モデルをクリックし、モデル名を入力してEnterキーを押し、確認をクリックします
![](./images/setting-api-edit-1.png)
APIページに戻り、保存をクリックします。
## サービスの追加
リストにないプロバイダーサービスクラウドプロバイダーのサービスや自分でデプロイしたサービスを使用する場合、「サービスの追加」ボタンでカスタムモデルを追加できます。使用方法は「モデルの追加」「方法2手動でのモデル追加」と同様なので、ここでは繰り返しません。

View File

@ -1,73 +0,0 @@
# MCPサーバーへの接続
Claude Desktopや他のMCPクライアント製品とは異なり、OpenMCPによるMCPサーバー接続の手順は非常にスムーズです。
:::info MCPクライアント
MCPクライアントとは、MCPプロトコルを通じて通信可能な大規模言語モデル対話クライアントのことで、通常はローカルで動作するアプリケーションウェブページにはファイルIOの権限がないためです。その製品形態は現在ほぼチャットボット形式で、chat.deepseek.comやchat.openai.comのようなウェブサイトで使用するものと類似しています。
:::
まず、VLEを開き、[[acquire-openmcp|OpenMCPの取得]]でOpenMCPのインストールを完了した後、pythonで最も簡単なmcpサーバーを作成し、mcpクライアントの接続をテストします。
## OpenMCPでワンクリック接続
[[first-mcp|最初のMCP]]の例では、mcpのtool、resource、promptとして3つの関数を宣言しました。OpenMCPでこれらを起動するのは非常に簡単で、右上のOpenMCPアイコンをクリックするだけで接続できます
![](./images/connect-simple.png)
ログインが完了し、図のように接続成功が表示されれば、現在mcpサーバーが正常に起動・接続されたことを意味します。
![](./images/connect-success.png)
## STDIO接続の起動
STDIOを接続オプションとする開発方案では、ワンクリックでの迅速な起動を提供しており、mcpプロセスを追加で起動する必要はありません。OpenMCPが自動的に接続と破棄を行います。
現在サポートされているプログラミング言語とそれに対応する起動パラメータは以下の通りです:
|言語|接続パラメータ|起動ディレクトリ|
|:-|:-|:-|
|python|uv run mcp run $\{file\} | 遡って最初に見つかったpyproject.tomlのディレクトリ|
|nodejs|node $\{file\}| 遡って最初に見つかったpackage.jsonのディレクトリ|
|go|go run $\{file\}| 遡って最初に見つかったgo.modのディレクトリ|
## SSE & Streamable HTTP接続の起動
SSEとStreamable HTTPという2つのリモート接続方式については、どのポートでサーバーが起動されているか分からない起動hostとportが見えない設定ファイルや環境変数に書かれている可能性があるためため、リモート接続の場合、自動サーバー作成はサポートしておらず、手動で起動オプションを設定する必要があります。
VLE左側のプラグインメニューにあるOpenMCPをクリックし、「MCP接続ワークスペース」ビューで+をクリックすると、新しい接続を作成できます。
![](./images/add-connection.png)
必要な通信方式を選択します。
![](./images/select-server-type.png)
MCP Serverのアドレスを入力します。
![](./images/connect-sse.png)
:::info
注意が必要なのは、異なる通信方式は一般的に異なるendpointを使用することです。現在のMCP serverの多くは以下の原則に従っています
SSEで起動する場合、デフォルトで/sseをendpointとして使用します。例http://localhost:8001/sse
Streamable Httpで起動する場合、デフォルトで/mcpをendpointとして使用します。例http://localhost:8001/mcp
もちろん、MCP Serverが2つの異なるendpointを使用して両接続方式を同時にサポートすることも可能で、Streamable Httpに移行したいが短期的にSSEを放棄できない状況に特に有効です
:::
## openmcpプラグインのコントロールパネル
VLEの左側にopenmcpのアイコンがあり、クリックするとopenmcpのコントロールパネルが表示されます。
![](./images/openmcp-control-panel.png)
現在のワークスペースで以前接続したmcpサーバーはここに表示されます。これは、openmcpがデフォルトでワークスペース起動時のmcp接続情報を`.openmcp/tabs.{server-name}.json`に保存しているためで、`{server-name}`はmcpサーバー接続成功時のサーバー名です。
:::warning
注意同じプロジェクト内で、名前が完全に同じmcpサーバーを2つ持つべきではありません。これにより`.openmcp/tabs.{server-name}.json`の接続情報保存が衝突し、未知のエラーが発生する可能性があります。
:::
任意のワークスペースで同じmcpサーバーを使用したい場合は、「インストール済みMCPサーバー」に成熟した耐久性のあるmcpサーバーを追加することを検討してください。この場所に追加されたmcpサーバーはグローバルに使用可能です。
「入門とヘルプ」では、入門用の参考資料をいくつか準備しています。ぜひご活用ください。

View File

@ -1,83 +0,0 @@
# MCP 基本デバッグ
## 基本デバッグ
[[quick-debug.md|クイックデバッグ]]では、mcpのデバッグ方法について簡単に説明しました。この章では、openmcpにおけるデバッグモジュールの特徴と高度な機能に焦点を当てます。
## タブ
openmcpはタブをデバッグプロジェクトの最小単位としており、バーの+をクリックすると新しいタブを作成できます。OpenMCPのtools、resources、promptsの基本使用はInspectorとほぼ同じですが、OpenMCPは自動的に左側のリソースリストを初期化します。Inspectorではこの手順を手動で行う必要があります。
## デバッグ内容の自動保存
openmcpにはテスト結果を自動保存する機能があります。以下の動作が発生すると、openmcpはタブとその内容を保存します
- タブを作成し、有効なデバッグプロジェクトを選択する
- デバッグページでデバッグ操作を行う(ツールの選択、ツールの実行、大規模モデルへの質問など)
現在のmcpプロジェクトのテストデータは`.openmcp/tabs.{server-name}.json`に保存されます。ここで`{server-name}`はmcpサーバーが正常に接続されたサーバー名です。
:::warning
注意同じプロジェクト内で、名前が完全に同じmcpサーバーバーを2つ持つべきではありません。これにより`.openmcp/tabs.{server-name}.json`の接続情報保存が衝突し、未知のエラーが発生する可能性があります。
:::
## インタラクティブテストでの迅速な再現
デバッグプロセスでは、大規模モデルの回答が不十分で、これがあるツールのエラーによるものである場合が避けられません。問題がツールにあるかどうかを迅速に特定するために、下部の小さな飛行機アイコンをクリックできます。
![](./images/llm-fast-debug.png)
クリックすると、OpenMCPは新しいテストtoolプロジェクトを作成し、当時大規模モデルが使用したパラメータを自動的に右側のフォームに記入します
![](./images/llm-fast-debug-result.png)
あなたがする必要があるのは、実行をクリックしてエラーオプションを確認または排除することだけです。
## Mookデータ
一連のmcp toolの応答を迅速にテストするために、mook data機能を提供しています。これにより、mcp toolのschemaに基づいて使用可能なパラメータのセットを迅速に生成し、mcp toolの機能をテストできます。
2種類のmook方法を提供しています。1つ目はmookボタンで、クリックすると実際の意味はないがフォームを埋めることができるmookデータが自動生成されます。下図の`mook`ボタンがこの機能のトリガーポイントです。
![](./images/common-mook.png)
また、AI mook機能も提供しており、AIを使用してmookデータを生成できます。このデータはより現実的で信頼性がありますが、まず[[connect-llm|大規模モデルの接続]]で大規模モデルを設定する必要があります。下図の`AI`ボタンがこの機能のトリガーポイントで、mookデータを生成するpromptをカスタマイズすることもできます。
![](./images/ai-mook.png)
## pydanticサポート
pythonのfastmcpを使用してtoolを作成する場合、インターフェースのタイプを宣言する方法は2つあります。1つはpythonのデフォルトtypingライブラリを使用して複雑なデータ構造を宣言する方法、もう1つはpydanticを使用して複雑な変数を宣言する方法です。以下は例です
```python
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
from typing import Optional, Union, List, NamedTuple
mcp = FastMCP('錦恢の MCP Server', version="11.45.14")
class PathParams(BaseModel):
start: str
end: str
@mcp.tool(name="test",description="用来测试")
def test(
params: PathParams,
test1: str,
test2: Union[str, List[str]] = Field("", description="测试参数2"),
test3: Optional[str] = Field(None, description="测试参数3")
):
return [test1, test2, test3, params]
```
これら2種類の宣言方法に対して内部変換を実装しているため、openmcpはどちらもサポートしています。特に、宣言した変数がオブジェクトである場合上記の`PathParams`など、openmcpのtoolデバッグウィンドウは「オブジェクト入力ボックス」を生成します。この入力ボックスは基本的な形式チェックとオートコンプリートをサポートしています
![](./images/object-input.png)
:::info オブジェクトとは?
ここでの「オブジェクト」はjavascriptの概念で、シリアライズ可能なデータタイプの中で基本データタイプを除いた部分を指します。例えば{ "name": "helloworld" }はオブジェクトです。オブジェクトはpythonではdictやnamedTupleに似ています。
:::
:::warning
openmcpは可能な限り多くの状況をサポートしていますが、生産環境ではmcp toolのパラメータをオブジェクトとして定義することは推奨しません。シンプルなデータタイプとして定義することで、大規模モデルがツールを呼び出す際の安定性をより高めることができます。
:::

View File

@ -1,43 +0,0 @@
# 実験結果の配布
## タブの復元
openmcpはデフォルトで実験結果をリアルタイムに保存します。ワークスペースで開かれた各サーバーは、結果を`.openmcp/tabs.{server-name}.json`に保存します。ここで`{server-name}`はmcpサーバー接続が成功したサーバー名です。
.gitignoreファイルに.openmcpフォルダに一致するルールが含まれていないことを確認してください。これにより、gitでコードをコミットしたり、agentのコードを管理したりする際に、他のコンピュータでcloneしたり、他の人があなたのプロジェクトをcloneした場合に、前回の実験内容を迅速に復元し、実験や開発デバッグを継続できます。
## 接続の復元
各mcpサーバーの接続情報は`.openmcp/connection.json`に保存されます。以下は例です:
```json
{
"items": [
[
{
"connectionType": "STDIO",
"command": "mcp",
"args": [
"run",
"main.py"
],
"url": "",
"cwd": "{workspace}/simple-mcp",
"oauth": "",
"clientName": "openmcp.connect.STDIO",
"clientVersion": "0.0.1",
"env": {},
"serverInfo": {
"name": "錦恢の MCP Server",
"version": "1.9.2"
},
"filePath": "{workspace}/simple-mcp/main.py",
"name": "錦恢の MCP Server",
"version": "1.9.2"
}
]
]
}
```
左側のコントロールパネルを開くか、過去に開いたmcpサーバーを開くと、mcpはデフォルトで上記の情報に基づいてワークスペースのサーバーリストを取得したり、自動接続を試みたりします。openmcpがmcpに接続する際に初期化エラーや保存エラーが発生した場合、openmcp公式に助けを求める以外に、`.openmcp/connection.json`ファイルを手動で管理することもできます。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Some files were not shown because too many files have changed in this diff Show More