Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

History
223 lines (169 loc) · 10.8 KB

File metadata and controls

223 lines (169 loc) · 10.8 KB

MCP — Overview and Architecture

Other sections:Quick start · Tools reference · Features and examples · Capabilities and metrics · Synergies and instructions · Flows and synergies (full steps)


Overview

MCP (Model Context Protocol) is a universal server for managing all AgentStack services through a single interface. MCP gives AI agents (Google Studio, Cursor, VS Code, and others) full access to the platform via a standardized set of tools.

Main characteristics

  • Protocol version: 2.0
  • Model: 1 tool (agentstack.execute); 62+ actions for steps — see GET /mcp/actions
  • Streaming support: Yes
  • Idempotency: Yes
  • Job tracking: Yes
  • Port: 8000 (via API Gateway)

Key capabilities

  • Full management — with proper permissions: full control over users, data, projects, scheduler, assets, buffs (CRUD and domain operations)
  • ✅ Full project management (create, read, update, delete; add/update/remove users; anonymous creation)
  • ✅ RBAC: rbac.get_roles, rbac.assign_role, rbac.revoke_role, rbac.check_permission; projects.update_user_role for role assignment
  • ✅ Authentication and authorization
  • ✅ Payment management
  • ✅ Task scheduler (create, get, update, list, cancel, execute, pool operations)
  • ✅ Analytics and metrics
  • ✅ API key management (create, list, delete)
  • ✅ Rules Engine / Logic (create, update, delete, get, list, execute)
  • ✅ Assets (create, get, list, update, delete)
  • ✅ Buff system (create, apply, extend, revert, cancel, get, list, limits, temporary/persistent effects)
  • ✅ Webhooks, Notifications, Wallets

Architecture

Project structure

mcp/
├── main.py # FastAPI app, middleware, registration
├── routes.py # API endpoints for tools
├── tools.py # Implementation of all MCP tools
├── sdk_wrapper.py # SDK wrapper for project operations
└── dependencies.py # Dependencies

Components

  1. FastAPI Application (main.py)

    • CORS middleware
    • Metrics middleware
    • Correlation ID tracking
    • Health checks
    • Prometheus metrics
  2. Routes (routes.py)

    • GET /mcp/discovery — discovery (single tool agentstack.execute)
    • GET /mcp/actions — list all actions by domain
    • POST /mcp — execute batch of steps (agentstack.execute)
    • POST /mcp/tools — JSON-RPC tools/call compatibility
    • POST /mcp/stream — streaming execution
    • GET /mcp/jobs/{job_id} — job status
    • OAuth, AI prompts, recipes, health, cache/clear under /mcp
  3. Tools Registry (tools.py)

    • All tools registered in MCP_TOOLS
    • Pydantic models for request validation
    • Error handling and logging
  4. SDK Wrapper (sdk_wrapper.py)

    • Wrapper over HTTP API for project operations
    • Uses existing public REST endpoints on agentstack.tech
    • Unified interface for all operations

Execute and discovery

A single tool agentstack.execute with batched steps and 494 catalog actions (see MCP_SCALE.md, MCP_CAPABILITY_MATRIX.md). One API, async jobs and streaming.

  • Base URL:https://agentstack.tech/mcp
  • Execute (sync):POST /mcp — body: { "steps": [ { "id": "p1", "action": "projects.create_project_anonymous", "params": { "name": "My app" } } ], "options": { "stopOnError": true } }
  • Execute (async job):POST /mcp with "options": { "async": true, "idempotency_key": "..." } → returns job_id; status via GET /mcp/jobs/{job_id}.
  • Execute (stream):POST /mcp/stream — same body, response is text/event-stream with started and completed events.
  • List actions:GET /mcp/actions — all valid action values by domain (projects, buffs, auth, payments, logic, assets, scheduler, analytics, etc.).
  • Discovery:GET /mcp/discovery — protocol, single-tool schema, streaming and jobs flags.
  • Health:GET /mcp/health — lightweight status (status, module, version, tools_count) plus discovery_url and actions_url.
  • AI help:POST /mcp/ai/plan_steps — suggests steps[] from goal and history.

Steps can reference previous results via { "from": "stepId.result.field" } and use optional if for conditions. See CONTEXT_FOR_AI_MCP.md and MCP_CAPABILITY_MAP.md.

Full management and permissions

MCP provides full management across all main domains when the caller has the required permissions:

DomainReadCreateUpdateDelete / CancelPermissions
Projectsget_projects, get_project, get_stats, get_userscreate_project, create_project_anonymousupdate_projectdelete_projectowner / ecosystem
Project membersget_usersadd_userupdate_user_roleremove_userowner or manage_users; add/remove — Professional
RBACrbac.get_roles, rbac.check_permissionrbac.assign_role (or projects.update_user_role)rbac.revoke_rolemanage_users / owner; owner cannot be assigned via rbac.assign_role
Schedulerget_task, list_tasks, get_pool_tasks, get_pool_task_detailscreate_taskupdate_taskcancel_task, delete_pool_task, clear_pool_taskswrite on scheduler
Assetsget, listcreateupdatedeleteproject + authentication
Buffsget_buff, list_active_buffs, get_effective_limitscreate_buffextend_buffrevert_buff, cancel_buffproject + authentication
Logicget, list, get_processors, get_commandscreateupdatedeleteproject + authentication
Data (generic)commands.execute (dna_crud: get, create, update, delete on entities)
Project currenciesassets.get, assets.listassets.create (type: currency)assets.updateassets.deleteCurrencies = assets with type=currency; full CRUD via assets.*
Walletswallets.list, payments.get_balancewallets.createwallets.deposit, wallets.transfer for deposits and transfers

The context: { "project_id", "user_id" } in the request body overrides the session for the whole batch; for the ecosystem (project_id=1) management operations on projects and users are available without Professional subscription checks.

Recommended call combinations

  • Profile + projects: 1) resources/readagentstack://me 2) tools/call with agentstack.execute and one step projects.get_projects (or a batch with refs).
  • Project context:POST /mcp with context: { "project_id": N } and steps; or tools/call with arguments: { "steps": [...], "context": { "project_id": N } } (context overrides session for the batch).
  • Chained steps: One batch: step 1 projects.get_projects, step 2 projects.get_users with params: { "project_id": {"from": "s1.result.projects[0].id"} }.
  • Buffs: Batch buffs.create_buff then buffs.apply_buff with buff_id: {"from": "create_step.result.buff_id"}; use response applied_buffs_summary for who got what.
  • Planning:POST /mcp/ai/plan_steps with goal (and optional history) then execute returned steps[] via POST /mcp or tools/call agentstack.execute.

API Endpoints

Public endpoints (no X-API-Key): Calls without the auth header are allowed for GET /mcp/tools (tool list) and for the projects.create_project_anonymous tool (create anonymous project and get keys). All other requests require X-API-Key.

Discovery and metadata

GET /mcp/tools

Returns the list of all available tools, grouped by category. Can be called without X-API-Key.

Response:

{
"tools": {
"auth": [...],
"payments": [...],
"projects": [...],
...
},
"version": "2.0",
"total_tools": 60,
"description": "Full AgentStack MCP integration..."
}

GET /mcp/discovery

Discovery endpoint for automatic capability detection.

Response:

{
"protocol_version": "2.0",
"capabilities": {
"streaming": true,
"idempotency": true,
"job_tracking": true
},
"services": {
"auth": {...},
"projects": {...},
...
}
}

Tool execution

POST /mcp (primary)

Single tool agentstack.execute: send a batch of steps. Each step has id, action (e.g. projects.get_projects, buffs.apply_buff — full list at GET /mcp/actions), params. Optional context: { "project_id", "user_id" } overrides session for all steps.

Request:

{
"steps": [
{ "id": "p1", "action": "projects.get_projects", "params": {} },
{ "id": "create", "action": "projects.create_project_anonymous", "params": { "name": "My Project" } }
],
"context": { "project_id": 123 }
}

Response:{ "success", "steps": [...], "applied_buffs_summary" (if any buff apply step succeeded) }

POST /mcp/tools/{tool_name} (compatibility)

Executes one action by name (for clients that call tools individually). Prefer POST /mcp with steps for batching and context override.

POST /mcp/tools/{tool_name}/stream

Executes the tool with a streaming response (Server-Sent Events).

Response: SSE stream with events:

  • status: started
  • status: processing
  • status: completed
  • status: error

GET /mcp/jobs/{job_id}

Returns the status of an async job.

Prompts and caching

  • prompts/list — Returns available prompts. Some clients (e.g. Cursor) call this repeatedly (e.g. on connect and when refreshing). The server caches the list for 60 seconds so repeated calls within that window do not recompute it.

Troubleshooting

POST /mcp returns 500 Internal Server Error (tools/call)

Symptom: Client (e.g. Cursor MCP) reports "Streamable HTTP error: Internal Server Error" when calling a tool (e.g. projects.get_projects).

Cause: Tool result contained non-JSON-serializable values (e.g. uuid.UUID, datetime). Responses from tools/call are now serialized via a single mechanism (serialize_for_json) before json.dumps, so UUID and datetime are converted to strings.

What to do:

  1. Check backend logs for the exact exception, e.g. TypeError: Object of type UUID is not JSON serializable near json.dumps or _handle_jsonrpc_request.
  2. Ensure the deployed backend includes the fix: in _handle_jsonrpc_request the tools/call branch uses serialize_for_json(result_payload) before json.dumps. Redeploy if needed.
  3. For other 500s on POST /mcp: retry with a smaller batch; confirm action id via GET /mcp/actions; ensure tool errors return structured isError in step results when the platform supports it. Contact support with request id if persistent.