Agent MCP(模型上下文协议)的核心作用是为AI应用连接外部工具和数据源提供一套标准化的“万能接口”。
MCP核心功能:
可以把它理解为Agent与外界的“通用翻译器”和“统一调度员”,具体体现在:
-
打破数据孤岛,让AI“耳聪目明”:AI模型通常无法直接访问实时数据或你的私有业务数据。MCP服务器通过标准化的“资源”和“工具”,让AI能安全地读取数据库、调用API、操作本地文件。例如,让一个客服Agent可以实时查询你的库存数据库。
-
告别“手写代码”的麻烦:在没有MCP时,每接入一个外部系统(如数据库、邮件服务),开发者都需要编写大量定制化代码。MCP让Agent能自动发现(
list_tools)和调用(call_tool)服务器提供的功能,当服务更新时,也无需修改Agent代码。 -
让Agent既能“想”,也能“做”:大模型(LLM)负责思考和规划,而Agent则通过MCP去“执行”。Agent可以将复杂任务拆解,然后通过MCP调用不同的工具来完成(如发送邮件、操作Excel、生成报表)。
-
保障企业级安全与合规:MCP在设计上内置了用户授权和同意的概念,所有工具调用和数据访问都需要明确的用户授权,这对于处理敏感数据的企业应用至关重要
MCP对接类型服务:
MCP 本质上是一个标准化的协议层,只要某服务能被 Python/Node.js 调用,就可以封装成 MCP 工具给 Agent 使用
API接口
REST/GraphQL
import json import sys import urllib.request import urllib.parse from typing import Any BASE_URL = "http://localhost:8081" def send_request(method: str, path: str, params: dict | None = None) -> dict: url = f"{BASE_URL}{path}" if params: query = urllib.parse.urlencode(params) url = f"{url}?{query}" req = urllib.request.Request(url, method=method) try: with urllib.request.urlopen(req, timeout=30) as resp: data = resp.read().decode("utf-8") return json.loads(data) if data else {} except Exception as e: return {"error": str(e)} def handle_list_tools() -> dict: return { "tools": [ { "name": "get_week_trend", "description": "获取测试报告周趋势数据", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "get_today_pass_rate", "description": "获取今日测试通过率", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "get_report_status", "description": "获取指定测试用例和报告的状态", "inputSchema": { "type": "object", "properties": { "testcaseId": {"type": "string", "description": "测试用例ID"}, "reportName": {"type": "string", "description": "报告名称"}, }, "required": ["testcaseId", "reportName"], }, }, { "name": "get_report_stats", "description": "获取测试报告统计数据", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "search_reports", "description": "搜索测试报告", "inputSchema": { "type": "object", "properties": { "keyword": {"type": "string", "description": "搜索关键词"}, }, }, }, { "name": "play_video", "description": "获取测试用例视频回放地址", "inputSchema": { "type": "object", "properties": { "testcaseId": {"type": "string", "description": "测试用例ID"}, }, "required": ["testcaseId"], }, }, { "name": "business_model", "description": "获取业务模块", "inputSchema": {"type": "object", "properties": {}}, }, ] } def handle_call_tool(name: str, arguments: dict) -> dict: if name == "get_week_trend": result = send_request("GET", "/api/reports/weekTrend") elif name == "get_today_pass_rate": result = send_request("GET", "/api/reports/todayPassRate") elif name == "get_report_status": tc = arguments.get("testcaseId") rn = arguments.get("reportName") result = send_request("GET", f"/api/reports/status/{tc}/{rn}") elif name == "get_report_stats": result = send_request("GET", "/api/reports/stats") elif name == "search_reports": kw = arguments.get("keyword") result = send_request("GET", "/api/reports/search", {"keyword": kw} if kw else None) elif name == "play_video": tc = arguments.get("testcaseId") result = send_request("GET", f"/api/reports/playVideo/{tc}") elif name == "business_model": result = send_request("GET", "/api/scenarios/business-modules") else: result = {"error": f"Unknown tool: {name}"} return {"content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}]} def main(): while True: line = sys.stdin.readline() if not line: break try: msg = json.loads(line) except json.JSONDecodeError: continue method = msg.get("method") msg_id = msg.get("id") resp: dict[str, Any] = {"jsonrpc": "2.0", "id": msg_id} if method == "initialize": resp["result"] = { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "test-report-mcp", "version": "0.1.0"}, } elif method == "tools/list": resp["result"] = handle_list_tools() elif method == "tools/call": params = msg.get("params", {}) resp["result"] = handle_call_tool(params.get("name"), params.get("arguments", {})) else: resp["error"] = {"code": -32601, "message": f"Method not found: {method}"} sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n") sys.stdout.flush() if __name__ == "__main__": main()

数据库
- PostgreSQL、MySQL、SQLite、MongoDB
- 让 Agent 直接查询数据库、分析表结构
- 常见项目: @modelcontextprotocol/server-postgres 、 @modelcontextprotocol/server-sqlite
""" 数据库 MCP Server Demo 支持 SQLite/MySQL/PostgreSQL,让 Agent 能查询数据库 配置: DB_TYPE=sqlite, DB_PATH=./demo.db DB_TYPE=mysql, DB_HOST=..., DB_USER=..., DB_PASS=..., DB_NAME=... """ import json import sys import os import sqlite3 from typing import Any # 默认数据库连接配置(硬编码,避免环境变量传递问题) DEFAULT_CONFIG = { "DB_TYPE": "mysql", "DB_HOST": "192.168.6.59", "DB_PORT": "3306", "DB_NAME": "metersphere", "DB_USER": "readonly_user", "DB_PASS": "", "DB_SSL_DISABLED": "true", } def get_env(key: str) -> str: """优先读取环境变量,否则使用默认配置""" return os.environ.get(key, DEFAULT_CONFIG.get(key, "")) def get_connection(): db_type = get_env("DB_TYPE") if db_type == "sqlite": return sqlite3.connect(get_env("DB_PATH") or "demo.db") elif db_type == "mysql": import pymysql return pymysql.connect( host=get_env("DB_HOST") or "localhost", port=int(get_env("DB_PORT") or "3306"), user=get_env("DB_USER") or "root", password=get_env("DB_PASS") or "", database=get_env("DB_NAME") or "", charset="utf8mb4", ssl_disabled=get_env("DB_SSL_DISABLED").lower() == "true", ) elif db_type == "postgres": import psycopg2 return psycopg2.connect( host=get_env("DB_HOST") or "localhost", port=get_env("DB_PORT") or "5432", user=get_env("DB_USER") or "postgres", password=get_env("DB_PASS") or "", database=get_env("DB_NAME") or "", ) else: raise ValueError(f"Unsupported DB_TYPE: {db_type}") def _serialize_row(row: tuple) -> list: """处理 datetime 等不可 JSON 序列化的类型""" result = [] for item in row: if hasattr(item, "isoformat"): result.append(item.isoformat()) else: result.append(item) return result def execute_query(sql: str) -> dict: conn = get_connection() try: cur = conn.cursor() cur.execute(sql) upper_sql = sql.strip().upper() if upper_sql.startswith("SELECT") or upper_sql.startswith("PRAGMA") or upper_sql.startswith("SHOW"): columns = [desc[0] for desc in cur.description] if cur.description else [] rows = cur.fetchall() return {"columns": columns, "rows": [_serialize_row(r) for r in rows], "count": len(rows)} else: conn.commit() return {"affected_rows": cur.rowcount} except Exception as e: return {"error": str(e)} finally: conn.close() def list_tables() -> dict: db_type = os.environ.get("DB_TYPE", "sqlite") if db_type == "sqlite": return execute_query("SELECT name FROM sqlite_master WHERE type='table'") elif db_type == "mysql": return execute_query("SHOW TABLES") elif db_type == "postgres": return execute_query("SELECT tablename FROM pg_tables WHERE schemaname='public'") return {"error": "Unsupported DB type"} def describe_table(table_name: str) -> dict: db_type = os.environ.get("DB_TYPE", "sqlite") if db_type == "sqlite": return execute_query(f"PRAGMA table_info({table_name})") elif db_type == "mysql": return execute_query(f"DESCRIBE {table_name}") elif db_type == "postgres": return execute_query( f"SELECT column_name, data_type FROM information_schema.columns WHERE table_name='{table_name}'" ) return {"error": "Unsupported DB type"} def handle_list_tools() -> dict: return { "tools": [ { "name": "list_tables", "description": "列出数据库中所有表", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "describe_table", "description": "查看表结构", "inputSchema": { "type": "object", "properties": {"table": {"type": "string", "description": "表名"}}, "required": ["table"], }, }, { "name": "execute_query", "description": "执行 SQL 查询(仅支持 SELECT)", "inputSchema": { "type": "object", "properties": {"sql": {"type": "string", "description": "SQL 语句"}}, "required": ["sql"], }, }, ] } def handle_call_tool(name: str, arguments: dict) -> dict: if name == "list_tables": result = list_tables() elif name == "describe_table": result = describe_table(arguments.get("table", "")) elif name == "execute_query": result = execute_query(arguments.get("sql", "")) else: result = {"error": f"Unknown tool: {name}"} return {"content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}]} def main(): while True: line = sys.stdin.readline() if not line: break try: msg = json.loads(line) except json.JSONDecodeError: continue method = msg.get("method") msg_id = msg.get("id") resp: dict[str, Any] = {"jsonrpc": "2.0", "id": msg_id} if method == "initialize": resp["result"] = { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "database-mcp", "version": "0.1.0"}, } elif method == "tools/list": resp["result"] = handle_list_tools() elif method == "tools/call": params = msg.get("params", {}) resp["result"] = handle_call_tool(params.get("name"), params.get("arguments", {})) else: resp["error"] = {"code": -32601, "message": f"Method not found: {method}"} sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n") sys.stdout.flush() if __name__ == "__main__": main()

文件系统
- 读写本地文件、目录浏览、文件搜索
- Agent 可以直接操作你电脑上的文件
- 常见项目: @modelcontextprotocol/server-filesystem
开发工具
- Git — 查看提交记录、分支管理、创建 PR
- GitHub/GitLab — 管理 Issue、PR、代码审查
- 常见项目: @modelcontextprotocol/server-github
""" Git/GitHub MCP Server Demo 让 Agent 能查看提交记录、分支、创建 PR 配置: GITHUB_TOKEN=your_token, REPO_PATH=./ """ import json import sys import os import subprocess import urllib.request from typing import Any REPO_PATH = os.environ.get("REPO_PATH", ".") GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "") def run_git(args: list[str]) -> dict: try: result = subprocess.run( ["git"] + args, cwd=REPO_PATH, capture_output=True, text=True, timeout=30, ) if result.returncode != 0: return {"error": result.stderr.strip()} return {"output": result.stdout.strip()} except Exception as e: return {"error": str(e)} def github_api(method: str, endpoint: str, data: dict = None) -> dict: if not GITHUB_TOKEN: return {"error": "GITHUB_TOKEN not set"} url = f"https://api.github.com{endpoint}" headers = { "Authorization": f"Bearer {GITHUB_TOKEN}", "Accept": "application/vnd.github+json", } body = json.dumps(data).encode() if data else None req = urllib.request.Request(url, data=body, method=method, headers=headers) try: with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode("utf-8")) except Exception as e: return {"error": str(e)} def handle_list_tools() -> dict: return { "tools": [ { "name": "git_log", "description": "查看 Git 提交记录", "inputSchema": { "type": "object", "properties": {"count": {"type": "integer", "default": 10}}, }, }, { "name": "git_branch", "description": "查看/创建分支", "inputSchema": { "type": "object", "properties": { "action": {"type": "string", "enum": ["list", "create"], "default": "list"}, "name": {"type": "string", "description": "分支名(create 时必填)"}, }, }, }, { "name": "git_status", "description": "查看工作区状态", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "github_create_pr", "description": "在 GitHub 上创建 Pull Request", "inputSchema": { "type": "object", "properties": { "repo": {"type": "string", "description": "owner/repo 格式"}, "title": {"type": "string"}, "head": {"type": "string", "description": "源分支"}, "base": {"type": "string", "description": "目标分支"}, "body": {"type": "string", "description": "PR 描述"}, }, "required": ["repo", "title", "head", "base"], }, }, { "name": "github_list_issues", "description": "列出 GitHub Issues", "inputSchema": { "type": "object", "properties": { "repo": {"type": "string", "description": "owner/repo 格式"}, "state": {"type": "string", "enum": ["open", "closed", "all"], "default": "open"}, }, "required": ["repo"], }, }, ] } def handle_call_tool(name: str, arguments: dict) -> dict: if name == "git_log": count = arguments.get("count", 10) result = run_git(["log", f"-{count}", "--oneline"]) elif name == "git_branch": action = arguments.get("action", "list") if action == "list": result = run_git(["branch", "-a"]) else: result = run_git(["branch", arguments.get("name", "")]) elif name == "git_status": result = run_git(["status", "--short"]) elif name == "github_create_pr": result = github_api("POST", f"/repos/{arguments['repo']}/pulls", { "title": arguments["title"], "head": arguments["head"], "base": arguments["base"], "body": arguments.get("body", ""), }) elif name == "github_list_issues": state = arguments.get("state", "open") result = github_api("GET", f"/repos/{arguments['repo']}/issues?state={state}") else: result = {"error": f"Unknown tool: {name}"} return {"content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}]} def main(): while True: line = sys.stdin.readline() if not line: break try: msg = json.loads(line) except json.JSONDecodeError: continue method = msg.get("method") msg_id = msg.get("id") resp: dict[str, Any] = {"jsonrpc": "2.0", "id": msg_id} if method == "initialize": resp["result"] = { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "git-mcp", "version": "0.1.0"}, } elif method == "tools/list": resp["result"] = handle_list_tools() elif method == "tools/call": params = msg.get("params", {}) resp["result"] = handle_call_tool(params.get("name"), params.get("arguments", {})) else: resp["error"] = {"code": -32601, "message": f"Method not found: {method}"} sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n") sys.stdout.flush() if __name__ == "__main__": main()
搜索引擎
- Google、Brave Search、Bing
- 让 Agent 具备实时联网搜索能力
- 常见项目: @modelcontextprotocol/server-brave-search
redis/缓存/消息队列
- Redis、RabbitMQ、Kafka
- 查看队列状态、管理缓存
""" Redis/缓存 MCP Server Demo 让 Agent 能操作 Redis 缓存 依赖: pip install redis 配置: REDIS_HOST=localhost, REDIS_PORT=6379, REDIS_PASSWORD=, REDIS_DB=0 """ import json import sys import os from typing import Any REDIS_HOST = os.environ.get("REDIS_HOST", "localhost") REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379")) REDIS_PASSWORD = os.environ.get("REDIS_PASSWORD", "") REDIS_DB = int(os.environ.get("REDIS_DB", "0")) def get_redis(): try: import redis return redis.Redis( host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD or None, db=REDIS_DB, decode_responses=True, ) except ImportError: raise RuntimeError("redis not installed. Run: pip install redis") def redis_get(key: str) -> dict: try: r = get_redis() value = r.get(key) ttl = r.ttl(key) return {"key": key, "value": value, "ttl": ttl} except Exception as e: return {"error": str(e)} def redis_set(key: str, value: str, ttl: int = 0) -> dict: try: r = get_redis() if ttl > 0: r.setex(key, ttl, value) else: r.set(key, value) return {"key": key, "set": True} except Exception as e: return {"error": str(e)} def redis_delete(key: str) -> dict: try: r = get_redis() deleted = r.delete(key) return {"key": key, "deleted": deleted} except Exception as e: return {"error": str(e)} def redis_list_keys(pattern: str = "*") -> dict: try: r = get_redis() keys = list(r.scan_iter(pattern, count=100)) return {"pattern": pattern, "keys": keys[:100]} except Exception as e: return {"error": str(e)} def redis_info() -> dict: try: r = get_redis() info = r.info() return { "used_memory_human": info.get("used_memory_human"), "connected_clients": info.get("connected_clients"), "total_keys": r.dbsize(), "db": REDIS_DB, } except Exception as e: return {"error": str(e)} def handle_list_tools() -> dict: return { "tools": [ { "name": "redis_get", "description": "获取 Redis 键值", "inputSchema": { "type": "object", "properties": {"key": {"type": "string"}}, "required": ["key"], }, }, { "name": "redis_set", "description": "设置 Redis 键值", "inputSchema": { "type": "object", "properties": { "key": {"type": "string"}, "value": {"type": "string"}, "ttl": {"type": "integer", "description": "过期时间(秒),0 表示永不过期"}, }, "required": ["key", "value"], }, }, { "name": "redis_delete", "description": "删除 Redis 键", "inputSchema": { "type": "object", "properties": {"key": {"type": "string"}}, "required": ["key"], }, }, { "name": "redis_list_keys", "description": "列出 Redis 键(支持通配符)", "inputSchema": { "type": "object", "properties": {"pattern": {"type": "string", "default": "*"}}, }, }, { "name": "redis_info", "description": "查看 Redis 状态信息", "inputSchema": {"type": "object", "properties": {}}, }, ] } def handle_call_tool(name: str, arguments: dict) -> dict: if name == "redis_get": result = redis_get(arguments.get("key", "")) elif name == "redis_set": result = redis_set(arguments.get("key", ""), arguments.get("value", ""), arguments.get("ttl", 0)) elif name == "redis_delete": result = redis_delete(arguments.get("key", "")) elif name == "redis_list_keys": result = redis_list_keys(arguments.get("pattern", "*")) elif name == "redis_info": result = redis_info() else: result = {"error": f"Unknown tool: {name}"} return {"content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}]} def main(): while True: line = sys.stdin.readline() if not line: break try: msg = json.loads(line) except json.JSONDecodeError: continue method = msg.get("method") msg_id = msg.get("id") resp: dict[str, Any] = {"jsonrpc": "2.0", "id": msg_id} if method == "initialize": resp["result"] = { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "redis-mcp", "version": "0.1.0"}, } elif method == "tools/list": resp["result"] = handle_list_tools() elif method == "tools/call": params = msg.get("params", {}) resp["result"] = handle_call_tool(params.get("name"), params.get("arguments", {})) else: resp["error"] = {"code": -32601, "message": f"Method not found: {method}"} sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n") sys.stdout.flush() if __name__ == "__main__": main()
云服务
- AWS、Azure、Google Cloud
- 管理云资源、查看日志、部署服务
- 常见项目: @modelcontextprotocol/server-aws
""" 云服务 MCP Server Demo (AWS) 让 Agent 能管理 AWS 资源(EC2/S3/Lambda) 依赖: pip install boto3 配置: AWS_ACCESS_KEY_ID=your_key AWS_SECRET_ACCESS_KEY=your_secret AWS_REGION=us-east-1 """ import json import sys import os from typing import Any def get_aws_client(service: str): try: import boto3 return boto3.client( service, region_name=os.environ.get("AWS_REGION", "us-east-1"), aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID", ""), aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY", ""), ) except ImportError: raise RuntimeError("boto3 not installed. Run: pip install boto3") def ec2_list_instances() -> dict: try: client = get_aws_client("ec2") resp = client.describe_instances() instances = [] for reservation in resp.get("Reservations", []): for inst in reservation.get("Instances", []): name = "" for tag in inst.get("Tags", []): if tag["Key"] == "Name": name = tag["Value"] instances.append({ "id": inst["InstanceId"], "name": name, "state": inst["State"]["Name"], "type": inst["InstanceType"], }) return {"instances": instances} except Exception as e: return {"error": str(e)} def s3_list_buckets() -> dict: try: client = get_aws_client("s3") resp = client.list_buckets() buckets = [{"name": b["Name"], "created": b["CreationDate"].isoformat()} for b in resp.get("Buckets", [])] return {"buckets": buckets} except Exception as e: return {"error": str(e)} def s3_list_objects(bucket: str, prefix: str = "") -> dict: try: client = get_aws_client("s3") resp = client.list_objects_v2(Bucket=bucket, Prefix=prefix, MaxKeys=100) objects = [] for obj in resp.get("Contents", []): objects.append({ "key": obj["Key"], "size": obj["Size"], "last_modified": obj["LastModified"].isoformat(), }) return {"bucket": bucket, "objects": objects, "count": len(objects)} except Exception as e: return {"error": str(e)} def lambda_list_functions() -> dict: try: client = get_aws_client("lambda") resp = client.list_functions() functions = [] for fn in resp.get("Functions", []): functions.append({ "name": fn["FunctionName"], "runtime": fn["Runtime"], "last_modified": fn["LastModified"], "memory": fn["MemorySize"], }) return {"functions": functions} except Exception as e: return {"error": str(e)} def handle_list_tools() -> dict: return { "tools": [ { "name": "ec2_list_instances", "description": "列出 AWS EC2 实例", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "s3_list_buckets", "description": "列出 AWS S3 存储桶", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "s3_list_objects", "description": "列出 S3 存储桶中的对象", "inputSchema": { "type": "object", "properties": { "bucket": {"type": "string"}, "prefix": {"type": "string", "default": ""}, }, "required": ["bucket"], }, }, { "name": "lambda_list_functions", "description": "列出 AWS Lambda 函数", "inputSchema": {"type": "object", "properties": {}}, }, ] } def handle_call_tool(name: str, arguments: dict) -> dict: if name == "ec2_list_instances": result = ec2_list_instances() elif name == "s3_list_buckets": result = s3_list_buckets() elif name == "s3_list_objects": result = s3_list_objects(arguments.get("bucket", ""), arguments.get("prefix", "")) elif name == "lambda_list_functions": result = lambda_list_functions() else: result = {"error": f"Unknown tool: {name}"} return {"content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}]} def main(): while True: line = sys.stdin.readline() if not line: break try: msg = json.loads(line) except json.JSONDecodeError: continue method = msg.get("method") msg_id = msg.get("id") resp: dict[str, Any] = {"jsonrpc": "2.0", "id": msg_id} if method == "initialize": resp["result"] = { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "cloud-aws-mcp", "version": "0.1.0"}, } elif method == "tools/list": resp["result"] = handle_list_tools() elif method == "tools/call": params = msg.get("params", {}) resp["result"] = handle_call_tool(params.get("name"), params.get("arguments", {})) else: resp["error"] = {"code": -32601, "message": f"Method not found: {method}"} sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n") sys.stdout.flush() if __name__ == "__main__": main()
监控(Prometheus)
- Prometheus、Grafana、Datadog
- 查询指标数据、告警状态
""" 监控系统 MCP Server Demo (Prometheus) 让 Agent 能查询 Prometheus 指标和告警 配置: PROMETHEUS_URL=http://localhost:9090 """ import json import sys import os import urllib.request import urllib.parse from typing import Any PROMETHEUS_URL = os.environ.get("PROMETHEUS_URL", "http://localhost:9090") def prometheus_query(query: str) -> dict: """执行 PromQL 即时查询""" url = f"{PROMETHEUS_URL}/api/v1/query?{urllib.parse.urlencode({'query': query})}" try: with urllib.request.urlopen(url, timeout=15) as resp: data = json.loads(resp.read().decode("utf-8")) if data.get("status") == "success": results = [] for item in data.get("data", {}).get("result", []): results.append({ "metric": item.get("metric", {}), "value": item.get("value", [None, None])[1] if item.get("value") else None, }) return {"query": query, "results": results} return {"error": data.get("error", "Unknown error")} except Exception as e: return {"error": str(e)} def prometheus_query_range(query: str, start: str, end: str, step: str = "60s") -> dict: """执行 PromQL 范围查询""" params = urllib.parse.urlencode({"query": query, "start": start, "end": end, "step": step}) url = f"{PROMETHEUS_URL}/api/v1/query_range?{params}" try: with urllib.request.urlopen(url, timeout=30) as resp: data = json.loads(resp.read().decode("utf-8")) if data.get("status") == "success": results = [] for item in data.get("data", {}).get("result", []): results.append({ "metric": item.get("metric", {}), "values": item.get("values", []), }) return {"query": query, "results": results} return {"error": data.get("error", "Unknown error")} except Exception as e: return {"error": str(e)} def prometheus_alerts() -> dict: """获取当前告警""" url = f"{PROMETHEUS_URL}/api/v1/alerts" try: with urllib.request.urlopen(url, timeout=15) as resp: data = json.loads(resp.read().decode("utf-8")) alerts = [] for alert in data.get("data", {}).get("alerts", []): alerts.append({ "name": alert.get("labels", {}).get("alertname"), "state": alert.get("state"), "severity": alert.get("labels", {}).get("severity"), "summary": alert.get("annotations", {}).get("summary"), "active_at": alert.get("activeAt"), }) return {"alerts": alerts, "count": len(alerts)} except Exception as e: return {"error": str(e)} def prometheus_targets() -> dict: """获取监控目标状态""" url = f"{PROMETHEUS_URL}/api/v1/targets" try: with urllib.request.urlopen(url, timeout=15) as resp: data = json.loads(resp.read().decode("utf-8")) targets = [] for target in data.get("data", {}).get("activeTargets", []): targets.append({ "job": target.get("labels", {}).get("job"), "instance": target.get("labels", {}).get("instance"), "health": target.get("health"), "last_error": target.get("lastError"), }) return {"targets": targets, "count": len(targets)} except Exception as e: return {"error": str(e)} def handle_list_tools() -> dict: return { "tools": [ { "name": "prometheus_query", "description": "执行 PromQL 即时查询", "inputSchema": { "type": "object", "properties": {"query": {"type": "string", "description": "PromQL 表达式"}}, "required": ["query"], }, }, { "name": "prometheus_query_range", "description": "执行 PromQL 范围查询", "inputSchema": { "type": "object", "properties": { "query": {"type": "string"}, "start": {"type": "string", "description": "开始时间 (Unix timestamp)"}, "end": {"type": "string", "description": "结束时间 (Unix timestamp)"}, "step": {"type": "string", "default": "60s"}, }, "required": ["query", "start", "end"], }, }, { "name": "prometheus_alerts", "description": "获取当前活跃告警", "inputSchema": {"type": "object", "properties": {}}, }, { "name": "prometheus_targets", "description": "获取监控目标状态", "inputSchema": {"type": "object", "properties": {}}, }, ] } def handle_call_tool(name: str, arguments: dict) -> dict: if name == "prometheus_query": result = prometheus_query(arguments.get("query", "")) elif name == "prometheus_query_range": result = prometheus_query_range( arguments.get("query", ""), arguments.get("start", ""), arguments.get("end", ""), arguments.get("step", "60s"), ) elif name == "prometheus_alerts": result = prometheus_alerts() elif name == "prometheus_targets": result = prometheus_targets() else: result = {"error": f"Unknown tool: {name}"} return {"content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}]} def main(): while True: line = sys.stdin.readline() if not line: break try: msg = json.loads(line) except json.JSONDecodeError: continue method = msg.get("method") msg_id = msg.get("id") resp: dict[str, Any] = {"jsonrpc": "2.0", "id": msg_id} if method == "initialize": resp["result"] = { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "prometheus-mcp", "version": "0.1.0"}, } elif method == "tools/list": resp["result"] = handle_list_tools() elif method == "tools/call": params = msg.get("params", {}) resp["result"] = handle_call_tool(params.get("name"), params.get("arguments", {})) else: resp["error"] = {"code": -32601, "message": f"Method not found: {method}"} sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n") sys.stdout.flush() if __name__ == "__main__": main()
AI模型
- OpenAI、Stability AI、本地模型
- 图片生成、语音合成、文本嵌入
""" AI 模型服务 MCP Server Demo 让 Agent 能调用多种 AI 能力:文本生成、语音合成、文本嵌入 配置: AI_API_KEY=your_api_key AI_BASE_URL=https://api.openai.com/v1 AI_MODEL=gpt-4o TTS_MODEL=tts-1 TTS_VOICE=alloy """ import json import sys import os import urllib.request from typing import Any API_KEY = os.environ.get("AI_API_KEY", "") BASE_URL = os.environ.get("AI_BASE_URL", "https://api.openai.com/v1") CHAT_MODEL = os.environ.get("AI_MODEL", "gpt-4o") TTS_MODEL = os.environ.get("TTS_MODEL", "tts-1") TTS_VOICE = os.environ.get("TTS_VOICE", "alloy") def chat_completion(messages: list[dict], model: str = None, temperature: float = 0.7) -> dict: if not API_KEY: return {"error": "AI_API_KEY not set"} payload = { "model": model or CHAT_MODEL, "messages": messages, "temperature": temperature, } data = json.dumps(payload).encode("utf-8") req = urllib.request.Request( f"{BASE_URL}/chat/completions", data=data, method="POST", headers={ "Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}", }, ) try: with urllib.request.urlopen(req, timeout=60) as resp: result = json.loads(resp.read().decode("utf-8")) return { "content": result["choices"][0]["message"]["content"], "model": result.get("model"), "usage": result.get("usage"), } except Exception as e: return {"error": str(e)} def text_to_speech(text: str, voice: str = None, output_file: str = "output.mp3") -> dict: if not API_KEY: return {"error": "AI_API_KEY not set"} payload = { "model": TTS_MODEL, "input": text, "voice": voice or TTS_VOICE, "format": "mp3", } data = json.dumps(payload).encode("utf-8") req = urllib.request.Request( f"{BASE_URL}/audio/speech", data=data, method="POST", headers={ "Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}", }, ) try: with urllib.request.urlopen(req, timeout=60) as resp: audio_data = resp.read() with open(output_file, "wb") as f: f.write(audio_data) return {"file": output_file, "size_bytes": len(audio_data), "text": text[:200]} except Exception as e: return {"error": str(e)} def text_embedding(text: str, model: str = "text-embedding-3-small") -> dict: if not API_KEY: return {"error": "AI_API_KEY not set"} payload = json.dumps({"model": model, "input": text}).encode("utf-8") req = urllib.request.Request( f"{BASE_URL}/embeddings", data=payload, method="POST", headers={ "Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}", }, ) try: with urllib.request.urlopen(req, timeout=30) as resp: result = json.loads(resp.read().decode("utf-8")) embedding = result["data"][0]["embedding"] return {"model": result.get("model"), "dimensions": len(embedding), "preview": embedding[:10]} except Exception as e: return {"error": str(e)} def handle_list_tools() -> dict: return { "tools": [ { "name": "chat_completion", "description": "调用大语言模型进行对话生成", "inputSchema": { "type": "object", "properties": { "messages": { "type": "array", "items": { "type": "object", "properties": { "role": {"type": "string", "enum": ["system", "user", "assistant"]}, "content": {"type": "string"}, }, }, "description": "对话消息列表", }, "model": {"type": "string", "description": f"默认 {CHAT_MODEL}"}, "temperature": {"type": "number", "default": 0.7}, }, "required": ["messages"], }, }, { "name": "text_to_speech", "description": "将文本转换为语音", "inputSchema": { "type": "object", "properties": { "text": {"type": "string", "description": "要转换的文本"}, "voice": {"type": "string", "description": "语音角色"}, "output_file": {"type": "string", "default": "output.mp3"}, }, "required": ["text"], }, }, { "name": "text_embedding", "description": "生成文本的向量嵌入", "inputSchema": { "type": "object", "properties": { "text": {"type": "string"}, "model": {"type": "string", "default": "text-embedding-3-small"}, }, "required": ["text"], }, }, ] } def handle_call_tool(name: str, arguments: dict) -> dict: if name == "chat_completion": result = chat_completion( arguments.get("messages", []), arguments.get("model"), arguments.get("temperature", 0.7), ) elif name == "text_to_speech": result = text_to_speech( arguments.get("text", ""), arguments.get("voice"), arguments.get("output_file", "output.mp3"), ) elif name == "text_embedding": result = text_embedding(arguments.get("text", ""), arguments.get("model", "text-embedding-3-small")) else: result = {"error": f"Unknown tool: {name}"} return {"content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}]} def main(): while True: line = sys.stdin.readline() if not line: break try: msg = json.loads(line) except json.JSONDecodeError: continue method = msg.get("method") msg_id = msg.get("id") resp: dict[str, Any] = {"jsonrpc": "2.0", "id": msg_id} if method == "initialize": resp["result"] = { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "ai-model-mcp", "version": "0.1.0"}, } elif method == "tools/list": resp["result"] = handle_list_tools() elif method == "tools/call": params = msg.get("params", {}) resp["result"] = handle_call_tool(params.get("name"), params.get("arguments", {})) else: resp["error"] = {"code": -32601, "message": f"Method not found: {method}"} sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n") sys.stdout.flush() if __name__ == "__main__": main()
浙公网安备 33010602011771号