mcp-portal
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-portalread src/config.py and src/env.py and tell me which one defines the retry limit"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-portal
mcp-portal is a stdio Model Context Protocol server that lets a frontier agent (Claude Code, Codex, Cursor, or any MCP host) delegate two jobs to the Cursor CLI on its own quota: bounded bulk_read (read explicitly selected files, answer with verified quotes) and code_write (generate boilerplate from a reference file + spec; the server writes the target file). Python stdlib only—no Node runtime and no MCP SDK dependency.
On 2026-09-08, composer-2.5-fast generated roughly 5× faster than a frontier model on the same brief (line-rate measurement). Cursor quota is separate from the host model's.
Quick start
uvx mcp-portalAlso available as pipx install mcp-portal / pip install mcp-portal, and listed in the
MCP Registry as io.github.apollion69/mcp-portal.
To run the development head instead of the release:
uvx --from git+https://github.com/apollion69/mcp-portal mcp-portalRequirements: Python 3.10+, the Cursor CLI (cursor-agent) installed and logged in.
Doctor (CLI inventory, no model call):
mcp-portal-doctorRelated MCP server: cursor-mcp-bridge
Configure per host
Claude Code
claude mcp add --scope user mcp-portal -- uvx mcp-portalCodex (~/.codex/config.toml)
[mcp_servers.mcp-portal]
command = "uvx"
args = ["mcp-portal"]
tool_timeout_sec = 150Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"mcp-portal": {
"command": "uvx",
"args": ["mcp-portal"]
}
}
}VS Code (.vscode/mcp.json, servers key)
{
"servers": {
"mcp-portal": {
"type": "stdio",
"command": "uvx",
"args": ["mcp-portal"]
}
}
}Generic mcpServers JSON
{
"mcpServers": {
"mcp-portal": {
"command": "uvx",
"args": ["mcp-portal"]
}
}
}Environment (optional):
Variable | Purpose |
| Cache, receipts, evidence (default |
| Path to |
Tools
bulk_read
Argument | Required | Description |
| yes | 1–16 file paths (relative to |
| yes | Question answered only from those files |
| no | Common root; default = longest common parent of |
| no | Override model; policy applies when omitted |
Returns status, run_id, answer.findings[] (file, start, end, quote, fact), gaps[], metrics, model_decision.
code_write
Argument | Required | Description |
| yes | What to generate |
| yes | Style/context reference file |
| no | If set, server writes this path |
| no | Override model |
Returns generated code, optional bytes_written, run_id, metrics.
status
No arguments. Returns CLI path, auth hint, default model, policy summary, cache location, receipt counters.
Model policy
Shipped in model-policy.json (package data). Defaults:
Prefer Cursor-native models (
composer-2.5, thencursor-grok-*)Strip
-fastsuffixes (never auto-select fast variants)Other vendors only when explicitly requested and listed by
cursor-agent --list-models
Override by editing model-policy.json in the installed package or setting policy fields via a custom file at MCP_PORTAL_HOME (future) — today, replace the package file or patch preferred in your fork. Each tool result includes model_decision.reason (default_preferred, fast_suffix_stripped, cursor_native_explicit, explicit_other_vendor, requested_unavailable_fallback).
How it works
Authorize — Server reads only listed paths; blocks credential-like paths and secret patterns.
Manifest — Request JSON includes per-file SHA-256 hashes.
Isolate — Cursor CLI runs with fresh
CURSOR_CONFIG_DIR, deny-all permissions,--mode ask, sandbox enabled.Verify — Every
quoteinbulk_readanswers must appear verbatim in the cited line range; bad citations are dropped or fail closed.Evidence — Per-run directory under
MCP_PORTAL_HOME/runs/<run_id>/with manifest (hashes, metrics; not full source).Budgets — 16 files, 128 KiB combined input, 90s timeout, bounded stdio frames.
Windows
On Windows, the delegate uses a local Cursor CLI run when either:
MCP_PORTAL_CLIpoints at an executable (including test stubs), orcursor-agent/agentis found onPATHand is a real file.
Otherwise it falls back to the wsl.exe bridge into Ubuntu/WSL (python3 -m mcp_portal.delegate --worker). Force either mode with MCP_PORTAL_BACKEND=local or MCP_PORTAL_BACKEND=wsl.
MCP config can use native
uvx mcp-portalwhen the CLI is on PATH, orwsl.exe+uvx mcp-portalwhen it is notHelpers in
clients/windows/(delegate.ps1,parse_read.ps1)MCP_PORTAL_WORKERoverrides the default WSL worker commandMCP_PORTAL_WSL_CDsets the WSL working directory (default~)
Optional Claude Code routing hook
Install read gate + skill (generic, transactional):
python3 -m mcp_portal.install_router prepare --client claude --python python3 \
--state-root ~/.cache/mcp-portal/router-tx --shell bash --command-shell bash
# then apply with the printed transaction idSee docs/skills/cursor-bulk-reader/SKILL.md for agent-facing guidance. The router blocks or warns on large full-file reads (>350 lines or >128 KiB) and points agents at bulk_read.
Repo-level MCP registration helper:
python3 -m mcp_portal.install plan
python3 -m mcp_portal.install apply --target claude-mcpSecurity
See SECURITY.md. Summary: you choose which files leave the machine; the CLI runs read-only with tools denied; quotes are verified server-side. Not a substitute for secret hygiene.
Related projects
Several Node-based bridges expose Cursor via MCP (different tradeoffs: SDK/Node stack, varying isolation and verification):
mcp-portal focuses on stdlib Python, hash-pinned manifests, quote verification, server-side writes for code_write, model policy, and WSL-first Windows support.
License
MIT — see LICENSE.
Available Tools
3 toolsbulk_readC
Read authorized files and answer a question via Cursor CLI (read-only).
| Name | Required | Description | Default |
|---|---|---|---|
| root | No | ||
| model | No | ||
| paths | Yes | ||
| question | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full behavioral burden. It does state read-only, which is useful, but does not disclose authorization requirements, rate limits, mutation side effects (none expected), or what 'via Cursor CLI' implies for execution. It also doesn't mention whether reading many files can fail partially.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that states the operation and its read-only nature. No wasted words; every clause adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter tool with no annotations and no output schema, the description is too thin. It does not cover required inputs beyond a name-level hint, execution environment ('Cursor CLI'), or expected output. It omits any guidance on the root/model parameters and file constraints.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It mentions 'paths' implicitly and 'question' implicitly, but does not explain the root, model, or the 16-file max, min 1 constraint, or formatting expectations for the question. Four params with zero coverage and minimal description leaves gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Read authorized files and answer a question via Cursor CLI.' It distinguishes itself from the code_write sibling by the read-only marker. However, it doesn't fully clarify how it differs from status or what 'bulk' scope means beyond the paths array.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance. It does not name an alternative or state conditions under which this read approach is preferable to alternatives. The read-only hint implies safe use but does not guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
code_writeC
Generate code from a spec and reference file; optional server-side write.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | Yes | ||
| model | No | ||
| target_path | No | ||
| reference_path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It discloses that a write is optional and server-side, which is useful, but says nothing about permissions, overwrite semantics for an existing target path, whether generation occurs without target_path, or side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with no filler, and the core action is front-loaded before the optional write clause. Nothing is wasted, though a semicolon joining two distinct modes is terse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool that can mutate the filesystem with no annotations, no output schema, and 0% parameter documentation, the description is thin. An agent cannot tell what is returned, whether existing files are overwritten, or how the model parameter affects behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% with 4 parameters, so the description must compensate. It loosely covers spec, reference_path, and target_path (via 'optional server-side write') but leaves the 'model' parameter entirely unexplained and adds no format or constraint detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a clear verb (generate) and its inputs (a spec and a reference file), plus the optional write behavior. It does not name or contrast against siblings bulk_read and status, but those tools are unrelated to code generation so differentiation is less critical.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool, when not to, or how it relates to the sibling tools. The phrase 'optional server-side write' hints at two modes but never states the condition that selects one over the other.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusB
Cursor CLI path, auth, cache location, and receipt counters.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. The listed fields (path, auth, cache, counters) strongly imply a non-mutating informational read, which is useful context, but the description never states that it is read-only or that it has no side effects. For a zero-parameter diagnostic, the risk is low, so this is adequate but not fully explicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact phrase with no filler, and the important content is front-loaded. It is terse to the point of being a fragment rather than a sentence, which slightly limits clarity but wastes nothing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, no-output-schema tool, the description's enumeration of returned fields is the main signal an agent lacks elsewhere, making it reasonably complete. It could still add an explicit read-only statement, but the core information is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to document, and the baseline for a no-param tool is 4. The description instead usefully characterizes the output, which the schema cannot do.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description enumerates the resource contents the tool reports (CLI path, auth, cache location, receipt counters), so an agent can infer it is a diagnostic/status read. However, it lacks an explicit verb such as 'Get' or 'Show', reading more like a field label than a stated purpose. It is distinguishable from the sibling tools, but only because they are unrelated names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives, nor any stated context or precondition. The sibling names bulk_read and code_write suggest unrelated functions, but the description provides no routing help at all.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
bulk_read - First observed
code_write - First observed
status
TDQS
Scored across 3 tools
Each tool serves a clearly distinct purpose: bulk_read is read-only Q&A, code_write generates and optionally writes code, and status reports configuration. There is no overlap in functionality that would cause misselection.
bulk_read and code_write use snake_case but with different modifier patterns (bulk_read is modifier+verb, code_write is noun+verb), while status is a bare noun. The mix makes the convention only partially predictable.
Three tools is within the typical 3-15 range and each earns its place for a focused portal. However, the surface feels slightly thin for a server handling both file reading and code generation.
The domain appears to be Cursor CLI operations for reading and writing code. Core create and read operations exist, but update, delete, and list operations are missing, leaving notable gaps for a full lifecycle.
Maintenance
Related MCP Connectors
Research-backed linting + generation for agent context files (CLAUDE.md, AGENTS.md, Cursor rules).
A paid remote MCP for OpenAI Codex agent coordination MCP, built to return verdicts, receipts, usage
Cross-agent artifact workspace with provenance across Claude Code, Codex, Cursor, LangGraph.
Real-time chat for AI agents. Claude Code, Cursor, Cline and Codex join channels over MCP.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceAn MCP server wrapping the Cursor CLI agent, enabling Claude Code and other MCP clients to delegate tasks to Cursor's AI agent for file writing, bash commands, and codebase queries.-
- AlicenseAqualityBmaintenanceMCP server that lets any agent or MCP host delegate tasks to the Cursor CLI agent for fast, headless execution. Supports task delegation, project discovery, file analysis, and follow-up sessions.314 npm3MIT
- AlicenseBqualityBmaintenanceA zero-friction stdio MCP bridge connecting Cursor Desktop to a local Hermes Agent, enabling natural language task delegation with session continuity and profile awareness.42Apache 2.0
- AlicenseBqualityBmaintenanceA fast, hardened MCP server that lets any MCP host drive the Cursor Agent CLI for heavy repo-aware tasks like search, analysis, planning, and edits, keeping host context small and token costs low.101MIT