Install
$ agentstack add mcp-hypen-code-gryphon ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Gryphon
> APIs were designed for developers. Gryphon makes them usable by AI agents.
[](https://github.com/hypen-code/gryphon/actions) [](https://www.python.org/) [](LICENSE)
Named for the legendary guardian, Gryphon sits between an agent's code and its API authority. It compiles OpenAPI catalogs, lets agents discover only the operations they need, and runs bounded Python through a credential-holding broker—not through unrestricted host execution.
The original idea remains: a small set of meta-tools, not one MCP tool per API endpoint. Discover → inspect → execute → reuse. Compose calls and reduce data in code before returning it to the model.
Version 2.0.0 · Python 3.13+ · FastMCP 4.0.2 · pydantic-monty 0.0.18. Real-client conformance tests cover MCP 2026-07-28 negotiation and legacy initialization. Native MCP Tasks are not implemented or advertised; background runs use portable application handles.
Gryphon is a local/operator deployment, not a completed multi-tenant SaaS. The distribution name is gryphon-runtime; the import package and CLI are gryphon. This version is not published to PyPI: install from this checkout.
Quick start
Prerequisites: Git, uv, and Python 3.13+. Use Linux/macOS, or the container deployment on Windows; persistent-store locks require POSIX support. The default restricted profile needs no Docker, model, model API key, or upstream credentials for the included offline demo.
Run these commands from the repository root:
git clone https://github.com/hypen-code/gryphon.git
cd gryphon
uv sync --frozen --extra dev
cp .env.example .env
cp config/swaggers.yaml.example config/swaggers.yaml
uv run --frozen gryphon compile
uv run --frozen python examples/demo.py
The config example uses [examples/weather.yaml](examples/weather.yaml), a local OpenAPI description of the public Open-Meteo forecast API. Compilation does not call the forecast endpoint. The demo uses a real in-process MCP client, computes a sum offline, then reuses the same recipe with new inputs. Compilation is optional for that computation; it adds weather discovery.
Connect an MCP client over stdio
uv run --frozen gryphon compile prints MCP client JSON to stdout, even when all sources are already up to date. Logs stay on stderr. Copy its mcpServers entry into your client's configuration; no client settings are changed automatically. Dry runs, failed/empty compilations, and compilation inside serve/run do not print client JSON.
The generated entry uses absolute storage paths, disables startup recompilation, and references the selected env-file path without copying its credentials. Keep operator settings/credentials in that private file or the launch environment. For this manual equivalent, replace /absolute/path/to/gryphon with your actual checkout path; clients may not expand ~.
{
"mcpServers": {
"gryphon": {
"command": "/absolute/path/to/gryphon/.venv/bin/gryphon",
"args": ["serve", "--env-file", "/absolute/path/to/gryphon/.env"],
"env": {
"GRYPHON_COMPILE_ON_STARTUP": "false",
"GRYPHON_COMPILED_OUTPUT_DIR": "/absolute/path/to/gryphon/compiled",
"GRYPHON_SWAGGER_CONFIG_FILE": "/absolute/path/to/gryphon/config/swaggers.yaml",
"GRYPHON_CACHE_DB_PATH": "/absolute/path/to/gryphon/data/cache.db",
"GRYPHON_RUN_DB_PATH": "/absolute/path/to/gryphon/data/runs.db",
"GRYPHON_ARTIFACT_DIR": "/absolute/path/to/gryphon/data/artifacts"
}
}
}
}
Stdio trusts the local operator. Run only one Gryphon process per run database: stop the demo or existing server before starting another against the same paths. Logs go to stderr so stdout remains available for the MCP protocol.
The MCP interface
| Core tool | Purpose | |---|---| | list_servers | Compact, paginated API summaries | | search_functions | Find relevant capabilities without loading the whole catalog | | get_functions | Inspect schemas and invocation metadata for 1–5 functions | | execute_code | Execute code with structured inputs and optional input_schema | | run_cached_code | Reuse unchanged source with a complete new params object | | submit_code | Submit work and receive a persistent run receipt | | get_run | Poll a caller-owned run | | cancel_run | Revoke an active run and wait for its worker to stop | | list_recipes | Search the caller's cached recipe summaries | | read_artifact | Read caller-owned JSON output in bounded chunks |
The reusable_code_guide prompt explains the execution contract on demand. With GRYPHON_ENABLE_ADDITIONAL_TOOLS=true, list_skills and get_server_skills expose optional server guides. Guides are untrusted data, not embedded in initialization instructions and never write approval.
Discovery responses include a registry fingerprint and truncation metadata. Follow next_cursor where provided; narrow searches when truncated. MCP readOnlyHint annotations are client hints, not authorization.
Call an API, then reuse the program
First search for weather, then call get_functions with:
{"functions": [{"server_name": "weather", "function_name": "get_forecast"}]}
Use the inspected schema, not guessed parameter names. This execute_code payload calls the public API, unlike the offline demo:
{
"code": "result = await call_tool(\"weather.get_forecast\", {\"latitude\": inputs[\"latitude\"], \"longitude\": inputs[\"longitude\"], \"current\": \"temperature_2m\"})",
"description": "current weather by coordinates",
"inputs": {"latitude": 51.5074, "longitude": -0.1278},
"input_schema": {
"type": "object",
"properties": {
"latitude": {"type": "number", "minimum": -90, "maximum": 90},
"longitude": {"type": "number", "minimum": -180, "maximum": 180}
},
"required": ["latitude", "longitude"],
"additionalProperties": false
}
}
Inside restricted Python, the only external capability has two arguments:
result = await call_tool("weather.get_forecast", {"latitude": inputs["latitude"], "longitude": inputs["longitude"], "current": "temperature_2m"})
Pass the returned cache_id to run_cached_code:
{"cache_id": "", "params": {"latitude": 48.8566, "longitude": 2.3522}}
inputsandparamsare JSON objects.paramsreplaces the entire input
object; it is not a patch and does not recover previous input values.
- Assign
resultto a JSON-native value. Nomain()is required; if you define
one, call it explicitly. Gryphon never auto-executes it.
- Restricted Python supports no imports, filesystem, direct network, or host
environment access. It is a subset, not a drop-in CPython environment.
input_schemais bounded. References, regex constraints, and combinators such
as $ref, pattern, allOf, anyOf, and oneOf are rejected.
- Recipe identity includes owner, exact source, schema, and catalog/policy
digest. Replay repeats validation and authorization; catalog or policy drift rejects stale recipes. Reordering or repeating the same exact write permits does not change policy identity; adding or removing a permit does. Input values are never rewritten into source.
- A recipe caches code, not an API response. Reuse can call the API again.
Results, background runs, and cancellation
Execution returns native structured MCP data with success, result data, handles when available, and stable error_type categories on failure. Docker backend unavailability retains sandbox_unavailable in tool results and saved receipts. Raw prints, upstream error bodies, and exception traces are omitted. A print-byte summary may be returned; do not use printing to deliver results.
Large successful results within the full-result limit become owner-scoped JSON artifacts. Use read_artifact with the returned artifact_id, then follow next_offset until eof. Requested chunks are at most 8192 bytes and may be smaller to fit the context budget. Artifacts do not bypass the full-result cap.
submit_code accepts the same code/input contract as execute_code, returns an id, and can be polled with get_run(run_id=...). Receipt states are queued, running, succeeded, failed, cancelled, and interrupted.
Optional idempotency_key values deduplicate matching requests within an owner while the receipt is retained; conflicting requests fail. This is not exactly-once delivery. On restart, persisted queued/running receipts become interrupted; code and writes are not automatically replayed or resumed. Check upstream state before deliberately retrying an interrupted write.
Cancellation revokes broker authority and waits for worker cleanup. It cannot undo an API action already accepted upstream. Receipt and artifact retention are bounded; they are not a permanent audit archive or durable workflow engine.
Configure APIs and policy
The public example is deliberately small:
servers:
- name: weather
swagger_url: ./examples/weather.yaml
is_read_only: true
swagger_url accepts local files or policy-approved HTTP(S) documents. Relative paths use the compilation working directory. base_url overrides the spec's URL. OpenAPI 3.0/3.1 and Swagger 2.0 produce v2 manifests with native parameter, JSON-body, and supported response schemas; OpenAPI 3.2 is not yet supported. Unsupported request semantics fail closed. Unsupported response schemas are reported and omitted, never presented as a validation guarantee. Supported output schemas are validated by the broker before results enter the sandbox. Optional query/header null means omission. Required/path null values and null query-array elements are rejected; JSON-body null is supported when declared.
Generated Python is documentation/SDK output, never imported or executed by the MCP host. Legacy top_level_functions selections do not promote direct MCP tools. --llm-enhance and GRYPHON_LLM_ENHANCE=true are explicitly rejected in v2: compilation is deterministic and needs no model key.
Credentials and writes
Public APIs need no auth block. For authenticated APIs, put environment references in trusted configuration, for example:
auth:
type: static
value: "Bearer ${UPSTREAM_API_TOKEN}"
Supported host-side auth types are static, jwt, basic, OAuth2 client credentials (oauth2), keycloak, and session. Dynamic tokens are fetched and cached by the broker. Set secrets in the operator environment or a private env file—not in code, tool inputs, committed YAML, or client configuration snippets. GRYPHON_{SERVER}_AUTH and JSON GRYPHON_{SERVER}_EXTRA_HEADERS are host-side options. Credentials are never injected into either execution sandbox.
is_read_only: true excludes write methods during compilation and is checked again by the broker. To permit a write, its source must allow writes, and the administrator must set both of these settings with exact inspected names (the operation below is illustrative):
GRYPHON_ALLOW_WRITES=true
GRYPHON_ALLOWED_WRITE_OPERATIONS=["orders.create_order"]
These are administrator permits, not an LLM approval flag. There is no interactive approval UI. API descriptions, guides, user code, and tool hints cannot change policy.
Important settings
See [.env.example](.env.example) and [GryphonConfig](src/gryphon/config.py) for the complete settings. Explicit environment variables override the env file. The default env file is .env in the working directory, with checkout-root fallback; use --env-file for an unambiguous location.
| Variable | Default | Meaning | |---|---|---| | GRYPHON_HOST / GRYPHON_PORT | 127.0.0.1 / 8000 | HTTP listener | | GRYPHON_HTTP_AUTH_TOKEN | unset | Required for HTTP; at least 32 characters | | GRYPHON_COMPILE_ON_STARTUP | true | serve compiles before startup | | GRYPHON_SANDBOX_MODE | restricted | Restricted API execution or offline docker | | GRYPHON_CONTEXT_BUDGET_BYTES | 16384 | Discovery response budget | | GRYPHON_DISCOVERY_LIMIT | 10 | Maximum items returned per discovery page | | GRYPHON_MAX_CODE_SIZE_BYTES | 65536 | Source byte limit | | GRYPHON_MAX_OUTPUT_SIZE_BYTES | 65536 | Inline output/print budget | | GRYPHON_MAX_RESPONSE_SIZE_BYTES | 2097152 | Full JSON/upstream response limit | | GRYPHON_EXECUTION_TIMEOUT_SECONDS | 30 | Deadline; restricted VM has a 30-second hard ceiling | | GRYPHON_MAX_CONCURRENT_EXECUTIONS | 4 | Active execution limit | | GRYPHON_QUEUE_TIMEOUT_SECONDS | 5 | Bounded admission wait | | GRYPHON_MAX_TOOL_CALLS | 50 | Per-run capability budget | | GRYPHON_SANDBOX_MEMORY_BYTES | 64000000 | Restricted VM memory budget | | GRYPHON_ALLOWED_DOMAINS | [] | Additional exact-host restriction; JSON array | | GRYPHON_ALLOW_PRIVATE_NETWORKS | false | Explicit private/loopback API opt-in | | GRYPHON_ALLOW_WRITES / GRYPHON_ALLOWED_WRITE_OPERATIONS | false / [] | Two-part write policy | | GRYPHON_CACHE_TTL_SECONDS / GRYPHON_CACHE_MAX_ENTRIES | 3600 / 500 | Recipe retention | | GRYPHON_RUN_TTL_SECONDS / GRYPHON_RUN_MAX_ENTRIES | 86400 / 1000 | Receipt retention | | GRYPHON_ARTIFACT_MAX_ENTRIES | 100 | Retained artifacts per owner |
Public API, authentication, and document destinations require HTTPS. GRYPHON_ALLOWED_DOMAINS additionally restricts exact hostnames; use a JSON array, not wildcards or CSV. HTTP is allowed only with private-network opt-in and solely approved private/loopback DNS answers. Metadata, link-local, reserved, and mixed public/private destinations remain denied. Clients use DNS pinning, origin-scoped pools, verified TLS, no environment proxies, and no redirects. See [SECURITY.md](SECURITY.md).
Operate Gryphon
uv run --frozen gryphon --version
uv run --frozen gryphon doctor
uv run --frozen gryphon compile --dry-run
uv run --frozen gryphon serve
uv run --frozen gryphon run
uv run --frozen gryphon --env-file /absolute/path/to/operator.env doctor
uv run --frozen gryphon doctor --env-file /absolute/path/to/operator.env
serve respects GRYPHON_COMPILE_ON_STARTUP; run compiles once, then serves. doctor reports read-only JSON diagnostics: it does not compile, open runtime stores, call APIs, or probe/start Docker. --env-file works before or after the subcommand.
Stop the server before cleaning. gryphon clean --yes reversibly renames only recognized compiled output and a closed recipe cache to adjacent .gryphon-archive-... paths. clean --yes --dry-run validates without moving; clean compile --yes archives then compiles. Unknown files, unsafe paths, links, and active SQLite sidecars are refused. Runs, artifacts, and config are retained. Restore manually while stopped by renaming an archive to its original path, without overwriting newer data. This is not an arbitrary-directory delete tool.
Authenticated HTTP
export GRYPHON_HTTP_AUTH_TOKEN="$(uv run --frozen python -c 'import secrets; print(secrets.token_urlsafe(48))')"
uv run --frozen gryphon serve --transport http
Connect to http://127.0.0.1:8000/mcp with an MCP client using Authorization: Bearer . HTTP startup refuses missing/short tokens; settings use SecretStr and the verified token maps to a fixed operator identity, distinct from stdio's local owner. Sharing a token shares that identity. Use a TLS reverse proxy before public exposure; bearer auth alone does not encrypt traffic or provide multi-tenant identity management.
Container service
After the quick-start config copies, set the random token above, then:
docker compose up --build -d
The root image uses the lockfile and runs as UID 1000. Compose uses restricted execution, read-only configuration, named volumes for compiled/data
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: hypen-code
- Source: hypen-code/gryphon
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.