mcp
GitHub用于管理 MCP 服务端工具、资源及契约的端到端工作流。涵盖影响分类、架构规范、中间件配置及测试要求,指导添加或修改 MCP 相关组件。
Trigger Scenarios
Install
npx skills add overmind-core/overmind --skill mcp -g -y
SKILL.md
Frontmatter
{
"name": "mcp",
"description": "End-to-end workflow for adding or changing Overmind MCP tools, resources, prompts, authentication, or result contracts — server layers, catalog registration, MCP-impact classification, contract versioning and required tests. Use when adding, changing, or removing an MCP tool, resource, prompt, auth rule, or CallToolResult contract."
}
Adding or changing MCP
The MCP server at /api/mcp/ is the project-scoped agent API. It shares domain services with the Console and REST API; it does not proxy either. This skill is for changing the server. The skills that overmind init installs for users live in overmind/skills/; never copy this file there.
MCP-impact classification
Every new or changed capability, API workflow or Console workflow needs an explicit MCP decision in the same change. Classify it:
- MCP-ready — an agent can discover, inspect or progress the workflow. Add or update the smallest tool, resource or prompt.
- CLI-guided — the workflow needs local files, repository edits, binary transfer or third-party credentials. MCP returns state, exact IDs and a structured action; the CLI or SDK does the local work.
- Frontend-only — presentation, navigation, visual exploration or billing with no useful agent action. The underlying state stays readable through MCP when agents need it.
- Out of scope — destructive operations stay off the public surface until designed and authorized.
Record the reason when a change is not MCP-ready. The Console must not become the only way to finish an agent-relevant workflow. Textual state is the baseline; charts may stay visual.
Shape of the server
MCP client
-> /api/mcp/ Streamable HTTP
-> MCPAuthMiddleware + MCPTransportMiddleware
-> request-scoped MCPContext
-> low-level MCP Server callbacks
-> curated ToolCatalog
-> feature tool adapter + strict input/output contracts
-> existing domain service / model / task
-> CallToolResult + resource links
-> client reads overmind:// resources or polls a job receipt
overbae/api/mcp.py is the entrypoint. overbae/asgi.py makes the MCP Starlette app the outer ASGI app and mounts Django inside it at /; its middlewares pass non-MCP paths through. /api/mcp/ and the OAuth routes never reach Django's ASGIHandler, so the outermost RequestThreadMiddleware gives each request a ThreadSensitiveContext (without it every thread-sensitive sync_to_async call shares one thread) and closes the request's DB connections. services/mcp/server.py owns the SDK server, stateless transport, protocol checks and middleware order. Never create a second MCP app or a feature-specific server.
With a PostHog token, the server sends $mcp_* analytics. Events carry identity, project_id and, on failure, error_code: before_send drops arguments, results and error text, $exception capture is off, and input models forbid extra fields so argument injection stays off. tests/test_mcp_analytics.py holds these rules.
Product activity is separate from analytics. Shared activity records back the
Console bell and onboarding milestones; overmind://activity pages those same
outcomes with offset, limit and path=agent|data. Account credentials add
project_id. report_onboarding_progress records the coding agent’s verified completed count
for one UUID run_id against the current SDK’s ten stages. These progress receipts
stay out of the notification feed; the landing page renders their roadmap.
The Console subscribes to /api/activity/events/ for project-scoped snapshots
and invalidates asset queries without page reloads. Task status changes
update the original activity ID; transformation publication reuses that task record.
Only newly observed changes trigger the brief asset highlight. Reconnects reconcile
the durable snapshot; onboarding receipts also advance the stream revision.
Reads and status polls never create action notifications or mark
them seen. Successful initialization retains credential-bound client identity;
connection milestones deduplicate by user, project scope and reported client
family, including across credential refreshes. Unknown or ambiguous identity stays
generic; client-reported logos never establish continuous agent presence.
Layer ownership
| Layer | Location | Responsibility |
|---|---|---|
| Transport | services/mcp/server.py |
Protocol, allowed hosts and origins, request-size limit, SDK callbacks |
| Authentication | services/mcp/auth.py, oauth.py |
API keys and OAuth tokens, credential limits, context binding |
| Context | services/mcp/context.py |
Immutable {user, token, project, client_ip, inference_base_url} for the request only |
| Catalog | services/mcp/catalog.py |
Curated visible tools, contract validation, handler calls, known failures |
| Contracts | services/mcp/contracts/ |
Strict Pydantic inputs and outputs, resource links, pages, job receipts |
| Feature adapters | services/mcp/tools_*.py |
Resolve project-scoped references and map an intent onto domain services |
| Domain logic | services/, innermind/, models, tasks |
Business rules, persistence, state transitions, background work |
| Results and errors | result_compat.py, errors.py |
Same typed output for every client; safe, stable errors |
| Resources | resources.py |
Read-only, project-scoped state and CLI handoff guidance |
| Prompts | prompts.py |
Multi-step workflow recipes composed from the public catalog |
Tools call the domain layer directly. They may share serializers or entity-resolution helpers, but never call frontend code, Console registries or an internal REST endpoint. If a Console workflow has no reusable service, fix the service boundary first.
Authentication
- Every request authenticates before the SDK callback. Account API keys and OAuth grants reach the user's active projects; project keys stay on one project. Every API key enforces its allowed IPs, and all credentials enforce
readandwrite. - Account credentials pass
project_idper operation;list_projectsreturns accessible projects. The catalog checks membership before the handler runs, and handlers get the project only fromMCPContext. Selection is per request, never session state. - OAuth uses the SDK protocol handlers with hashed codes and tokens in
models/mcp_oauth.py. Public clients register with auth methodnoneand S256 PKCE, against the exactMCP_SERVER_URLresource. Access tokens last one hour; refresh tokens rotate, and reuse revokes the family. OAuth works only on MCP; API keys useX-Api-KeyorAuthorization: Bearer(orApi-Key). ToolDefinition.required_scopesrecords the capability a tool needs; visibility enforces read versus write. Granular enforcement, if added, belongs in the catalog or auth layer for every tool, never in a handler.- Tool names containing
delete,remove,cancel,retryorundeployare rejected unless they are in_ALLOWED_LIFECYCLE_TOOLS(catalog.py); the destructive ones are also in_DESTRUCTIVE_TOOLS. Adding to either list needs explicit approval. Do not infer generic destructive operations from the existing entries.
Adding or changing a tool
- Classify the change. Reuse a tool when the agent intent is unchanged; do not mirror a REST endpoint because it exists.
- Add strict request and response models in
services/mcp/contracts/<domain>.py. ExtendMCPModel, bound collections and strings, reject unknown fields. - Put the handler in
services/mcp/tools_<domain>.py. Resolve entities insidecontext.project, call the domain service, and raiseMCPErrorfor expected failures. - Register one
ToolDefinitionin that module'sregister_<domain>_toolswith accurateread_only,idempotent,open_world,required_scopes,cost_classandasync_mode. Import a new domain module intoCATALOGonly when it is genuinely new. - Return the declared output model, never a raw dict. Add
resourceorresource_linksfor durable entities. - For background work, return a
JobReceiptwithkind,id,statusand anovermind://jobs/{kind}/{id}resource, and teachget_joband the resource reader that kind. - Operations that start paid or long work take a stable
request_key; an identical retry returns the original receipt and a changed payload conflicts. - Bump
CONTRACT_VERSIONinservices/mcp/__init__.pywith every contract change.overmind://interface/currentpublishes it with the catalog fingerprint. - Keep
tools/listwithinMAX_MANIFEST_BYTES(tests/mcp_fixtures.py); output schemas and secrets stay out of discovery.
Keep handlers thin. Never copy a Console view's business logic into tools_*.py.
Results and errors
ToolCatalog.call validates input, runs the handler, validates output, then tool_result emits the same object as structuredContent and as compact JSON text for clients that read only text. Matching resource/resource_links also become native ResourceLink content. Identifiers, costs, rows and receipts are contract fields, never prose only.
MCPError becomes {"error": {"code", "message", "retryable", "fields"}} with isError=true. Unexpected failures become a safe internal_error. Messages come from authored text or authored domain errors; never leak raw exceptions, provider responses, tokens or tracebacks.
Bound tool responses losslessly: page large results, or fail with a typed error such as query_result_too_large, rather than clip values. Action receipts stay compact and point to a resource with the full evidence.
Resources, jobs and local files
- Resources are durable, read-only state, not a second mutation API. Implement the project-filtered payload in
resources.py, register its template, and build links withresource_link. safe_jsonis the resource serialization boundary. It drops keys that name a token, secret, password, cookie, credential, authorization, API key or private key (numeric token counts stay), and it truncates strings at 12,000 characters and collections at 100 entries.safe_finetune_progressalso removes presigned and checkpoint URLs.- Reads never invoke a worker or a provider. Operational, monitoring and evaluation evidence come from receipts that background controllers saved.
- MCP carries JSON, not local bytes. Uploads, exports, checkpoints, repository edits and local execution return a CLI guidance resource with exact IDs and argv; MCP resumes at the resulting resource.
- Essential client-independent guidance belongs in server instructions, tool descriptions and resources. Plugins and installed skills are optional; never make one a prerequisite or the enforcement boundary. The
overmind/.{claude,codex,cursor}-plugin/versions matchSKILLS_VERSIONinovermind/overmind/skills_db.py.
Prompts and catalog discipline
Prompts are named, parameterized recipes. They name the public tools to call, mark approval and human-action points, and end with a decision checkpoint. Do not add a prompt to cover a missing tool, or a tool for one prompt sentence.
Organize the catalog by intent: discovery and read, mutation, background work, CLI handoff. A description states the goal, the main constraint and the next state. Prefer one broad inspection tool to near-duplicate filters; distinct state transitions deserve distinct tools.
Tests
Follow the testing policy in AGENTS.md and the run-tests skill. A tool's happy path belongs to its vertical's journey; these files hold the edge cases. Call tools through mcp_fixtures.call_tool; only auth and transport tests go through the ASGI app (mcp_fixtures.asgi_db).
| Change | Coverage |
|---|---|
| Contract or catalog metadata | tests/test_mcp_catalog.py, tests/test_mcp_manifest.py |
| Feature tool | tests/test_mcp_<domain>.py: project isolation, expected errors, structured output, returned IDs |
| Result format | tests/test_mcp_result_compat.py |
| Resource or job kind | tests/test_mcp_resources.py |
| Auth or transport | tests/test_mcp_authorization.py, test_mcp_oauth.py, test_mcp_api_keys.py, test_mcp_account_access.py, test_mcp_transport.py |
| Prompt or CLI handoff | tests/test_mcp_prompts.py; overmind/tests/ for CLI behavior |
Completeness
- The MCP classification, and the reason when not MCP-ready, is in the PR.
- The tool, resource or prompt uses the shared domain service and project-scoped authorization.
- Inputs, structured outputs, resource links and async receipts are defined and tested.
- The entity has a read path after creation, including polling for background work.
- Local-file workflows use CLI guidance, not an MCP byte-transfer workaround.
-
CONTRACT_VERSION, the catalog, prompts, resources, the user-facing skills inovermind/skills/and the MCP tests change together. Regenerate the API client when the REST contract changed.
Activity sequence_key identifies a project-scoped dataset preparation workflow:
creation, upload, import, saved transformations, previews and publication. Pipeline
runs resolve their dataset from the retained run record. Other edits and consumers
remain separate. The Console connects adjacent matching events without declaring
whole-task completion.
An explicit start_dataset_preparation / update_dataset_preparation lifecycle keeps
the dataset Preparing between jobs until the agent finishes. Inspect it through
inspect_dataset_workbench.preparation_workflow. Child source and pipeline activity
remains recorded but is folded into its single evolving notification; child updates
touch the parent timestamp to invalidate Console assets. Pause is explicitly reported,
not inferred from a client disconnect.
Version History
-
fe6ddf7
Current 2026-11-02 09:23
重构测试套件以围绕产品覆盖地图;连接编码代理入职与活动到控制台;对齐 Dev Skills 并修剪 AGENTS.md;使 create_api_key 项目可选;修复入职提示词;移除自动 OCR 语言检测;添加并行可恢复 OCR。
- e146ecd 2026-10-18 15:42


