github / github/github-mcp-server
Feature Request: `get_agent_card` tool — load ALP-compatible agents directly from GitHub repos
- 主要言語
- Go
- スター
- 33k
- フォーク
- 5k
- 平均マージ
- 2日 1時間
- マージ済み PR(30日)
- 52
説明
## Summary
Add a `get_agent_card` tool to the GitHub MCP Server that reads a
structured agent descriptor file from any repository and returns it as a
parsed, schema-validated JSON object.
The tool defaults to `agent.alp.json` at the repo root, with an optional
`filename` parameter to support any structured agent descriptor format a
developer may use.
This closes the last gap between an agent living in a GitHub repo and that
agent being live in any MCP-compatible runtime (Kiro, Claude Code, Claude
Desktop, VS Code, Cursor) — in one tool call.
---
## Background: what ALP is
Agent Load Protocol (ALP) is an open, MCP-compatible format for describing
complete AI agents as a single portable artifact — the Agent Card
(`agent.alp.json`).
What MCP is to tools, ALP is to entire agents.
An Agent Card declares:
- `id`, `name`, `description` — agent identity
- `persona` — the full system prompt
- `tools[]` — MCP-compatible tool endpoints (local or proxied HTTP)
- `memory` — session/persistent memory config
- `llm` — provider preference (any, user-resolved)
- `server.url` + `server.transport` — where the ALP Server lives
- `toolsets`, `security.read_only`, `pagination` — runtime control fields
- (mirrors concepts already in the GitHub MCP Server)
Current version: v0.9.0
Spec + reference implementation:
https://github.com/RodrigoMvs123/agent-load-protocol
Live demo MCP endpoint:
https://agent-load-protocol.onrender.com/mcp
Any MCP host can load the live demo agent today with:
```json
{
"mcpServers": {
"hello-agent": {
"type": "http",
"url": "https://agent-load-protocol.onrender.com/mcp"
}
}
}
```
---
## The gap this tool closes
The GitHub MCP Server already has `get_file_contents`, which can read any
file from a repo — including `agent.alp.json`.
However, it returns a raw base64-encoded blob. The caller must:
1. Decode
2. JSON-parse
3. Validate manually
before the agent can be used.
`get_agent_card` would instead return a typed, schema-validated JSON object
directly usable by any ALP-aware runtime.
This is the difference between `GET /blob` and `GET /agent` — structured
semantics vs raw bytes.
---
## Agent definitions: file vs. API level
Developers today define agents in two fundamentally different ways.
### API-level definition (e.g. Anthropic Managed Agents)
When using a managed agent platform, the agent is defined entirely inside
an API call — no file is ever committed to a repository:
```json
POST /v1/agents
{
"name": "My Assistant",
"model": "claude-sonnet-4-20250514",
"system_prompt": "You are a helpful assistant.",
"tools": [
{ "type": "bash" },
{ "type": "web_search" }
],
"mcp_servers": [
{ "type": "http", "url": "https://my-server.com/mcp" }
]
}
```
The platform responds with an `agent_id`. The definition lives in managed
infrastructure, not in the GitHub repo. A developer following this path
has no descriptor file for `get_agent_card` to read.
**This is outside the scope of `get_agent_card`.** The tool operates on
files committed to a repository. API-level agent definitions are not
reachable by a file-reading tool — this is an explicit boundary, not a
gap to be solved here.
### File-level definition (repo-committed descriptor)
When a developer commits a structured agent descriptor to their repo,
`get_agent_card` can read it, parse it, validate it, and return a typed
object in one call — regardless of which format the descriptor follows.
This is the scope `get_agent_card` is designed for.
---
## Proposed tool
**Tool name:** `get_agent_card`
**Toolset:** `repos` (existing) — or a new lightweight `alp` toolset
**Required OAuth scope:** `repo` (same as `get_file_contents`)
### Input parameters
| Parameter | Type | Required | Description |
|------------|--------|----------|-------------|
| `owner` | string | yes | Repository owner |
| `repo` | string | yes | Repository name |
| `ref` | string | no | Branch, tag, or commit SHA (defaults to repo default branch) |
| `path` | string | no | Path to the card file (defaults to `agent.alp.json` at repo root) |
| `filename` | string | no | Override the descriptor filename (defaults to `agent.alp.json`). Supports any structured agent descriptor format stored in the repo. |
### Filename parameter — design rationale
Developers building agents with different frameworks may store their agent
descriptor under different filenames:
- `agent.alp.json` — ALP format (default)
- `.github/agent.json` — GitHub-native convention
- `agent-card.json` — AI Catalog alignment
- Any other structured JSON descriptor
The `filename` parameter is not a format selector — it is a filepath
instruction to the GitHub file API. The tool fetches whatever file lives
at that path, decodes the base64 content, parses it as JSON, and returns
it as a structured object.
Validation behavior:
- If `alp_version` is present in the parsed JSON → ALP schema validation
runs and any offending fields are reported
- If `alp_version` is absent → ALP validation is skipped and the raw
parsed JSON is returned as-is
This means the tool works correctly for any JSON descriptor format. A
caller using ALP gets schema validation automatically. A caller using a
different format gets a clean JSON object without ALP-specific errors.
| Convention | filename value | ALP validation |
|---|---|---|
| ALP (default) | `agent.alp.json` | ✅ runs |
| AI Catalog | `agent-card.json` | skipped, raw JSON returned |
| GitHub-native | `.github/agent.json` | skipped, raw JSON returned |
| Custom | any `.json` path | skipped, raw JSON returned |
This avoids permanent lock-in to a single format while remaining
immediately useful today.
### Output (parsed Agent Card object)
```json
{
"alp_version": "0.9.0",
"id": "my-agent",
"name": "My Agent",
"persona": "You are a helpful assistant.",
"tools": [
{
"name": "search",
"description": "Search the knowledge base.",
"endpoint": "https://my-server.com/api/search"
}
],
"server": {
"url": "https://my-alp-server.com",
"transport": "http"
},
"llm": { "provider": "any" },
"memory": { "enabled": false }
}
```
If the file is not found at the given path, the tool returns a clear error.
If the file exists but fails ALP schema validation, the tool returns a
validation error identifying the offending fields.
---
## How it unlocks the full GitHub → Kiro flow
With this tool approved and shipped, the end-to-end flow becomes:
```
Developer commits agent.alp.json to any GitHub repo
↓
Kiro (or any MCP host) calls get_agent_card { owner, repo }
↓
GitHub MCP Server fetches + parses + validates the card
↓
ALP runtime (Kiro) reads persona → injects into LLM context
ALP runtime reads tools[] → registers MCP-compatible endpoints
↓
Agent is live in the Kiro chat window
```
No local clone. No manual config. One tool call.
This is the scenario that ALP's remote card mode (v0.6.0) was designed for:
- Ship `agent.alp.json` in your GitHub repo
- Point a runtime at it
- Agent is live
The GitHub MCP Server is the natural discovery bridge — it already sits
between GitHub and every major IDE.
`get_agent_card` completes that bridge.
---
## Real-world implementation — `hello-agent-alp-kiro` (ALP v0.9.0)
Since this issue was opened, a real ALP v0.9.0 agent following this exact
pattern has been built, deployed, and tested in Kiro.
**Repository:** https://github.com/RodrigoMvs123/hello-agent-alp-kiro
**Live Agent Card:** https://hello-agent-alp-kiro.onrender.com/agent
**Live MCP endpoint:** https://hello-agent-alp-kiro.onrender.com/mcp
All 4 tools (`greet`, `echo`, `get_agent_card`, `chat`) have been verified
in Kiro.
### How the flow works today (without get_agent_card)
Kiro currently uses `get_file_contents` to read the card:
```
get_file_contents({
owner: "RodrigoMvs123",
repo: "hello-agent-alp-kiro",
path: "agent.alp.json"
})
→ returns base64 blob → manual decode → manual JSON parse → no schema validation
```
Then `create_workflow_dispatch` to trigger deployment:
```
create_workflow_dispatch({
owner: "RodrigoMvs123",
repo: "hello-agent-alp-kiro",
workflow_id: "deploy.yml"
})
→ GitHub Actions injects secrets → agent deploys to Render → Kiro connects to /mcp
```
This works. But the `get_file_contents` step is the exact gap described in
this issue.
### What get_agent_card would replace
Exactly one step:
```
// today
get_file_contents({ owner, repo, path: "agent.alp.json" })
→ base64 blob, no validation, caller parses manually
// with get_agent_card
get_agent_card({ owner: "RodrigoMvs123", repo: "hello-agent-alp-kiro" })
→ typed, schema-validated Agent Card
→ runtime.deploy block surfaced directly — trigger, workflow path, credential refs
→ clear error if agent.alp.json is missing or malformed
```
The `runtime.deploy` block (new in ALP v0.9.0) is what makes this
structured:
```json
"runtime": {
"deploy": {
"trigger": "github_actions",
"workflow": ".github/workflows/deploy.yml",
"credentials": [
{ "ref": "GEMINI_API_KEY", "source": "github_secrets" },
{ "ref": "RENDER_API_KEY", "source": "github_secrets" },
{ "ref": "RENDER_SERVICE_ID", "source": "github_secrets" }
]
}
}
```
When `get_agent_card` returns this as a typed object, Kiro knows
immediately — without parsing a blob — that this agent deploys via GitHub
Actions, what workflow to trigger, and what credentials are declared. The
rest of the flow follows automatically.
The pattern works today with `get_file_contents` as a workaround.
`get_agent_card` makes it first-class.
---
## Alignment with existing GitHub MCP Server patterns
| GitHub MCP Server feature | ALP equivalent |
|---|---|
| `--toolsets` flag / `GITHUB_TOOLSETS` env var | ALP `toolsets.groups` + `toolsets.active` |
| `--read-only` flag | ALP `security.read_only` + per-tool `readonly: false` |
| `--dynamic-toolsets` beta | ALP `tools_discovery.mode: "dynamic"` |
| `server.json` manifest at repo root | ALP `server.alp.json` manifest at server root |
| `--insiders` / insiders URL | ALP `server.channel: "insiders"` + `insiders_url` |
| Tool description env-var overrides | ALP `description_override_key` per tool |
| Deprecated tool aliases | ALP `tools[].aliases` + `tools[].deprecated` |
ALP modeled several of these fields directly from the GitHub MCP Server
architecture.
`get_agent_card` is a natural extension in the same direction.
---
## Implementation sketch
```go
// In pkg/github/repos.go (or a new alp.go file in the repos toolset)
func GetAgentCard(owner, repo, ref, path, filename string) (*ALPCard, error) {
// 1. Resolve filename (default: "agent.alp.json")
if filename == "" {
filename = "agent.alp.json"
}
// 2. Resolve path (default: filename at repo root)
if path == "" {
path = filename
}
// 3. Call existing GetFileContents(owner, repo, path, ref)
// 4. Decode base64 content
// 5. json.Unmarshal into map[string]interface{} or ALPCard struct
// 6. If alp_version field present → validate against ALP schema
// If alp_version field absent → skip validation, return raw parsed JSON
// 7. Return parsed struct (or validation error)
}
```
The implementation wraps `get_file_contents` — no new GitHub API calls
needed.
ALP JSON schema:
https://github.com/RodrigoMvs123/agent-load-protocol/blob/main/schema/agent.alp.schema.json
---
## Optional: server.alp.json companion endpoint
ALP v0.3.0+ defines a `server.alp.json` manifest that ALP-aware clients
read before the full agent card to understand server capabilities:
- Supported transports
- Auth methods
- Available channels
A companion tool:
- `get_alp_server_manifest`
- or `include_server_manifest` (boolean flag on `get_agent_card`)
would surface this in one call.
This mirrors the GitHub MCP Server's own `server.json` at the repo root.
---
## Considered alternative: use get_file_contents directly
Yes, `get_file_contents` already works. A client can:
1. Fetch file
2. Decode base64
3. Parse JSON manually
However, a dedicated tool is still valuable:
- **Structured output** — returns a typed object, not a blob
- **Schema validation** — catches malformed ALP cards early
- **Discoverability** — `get_agent_card` is self-explanatory
- **Default path resolution** — encodes `agent.alp.json` convention
- **Filename flexibility** — `filename` parameter supports other formats
- **Explicit scope boundary** — tool is repo-scoped by design; API-level
agent definitions (e.g. Anthropic Managed Agents) are outside its scope
- **Future-proofing** — centralizes validation logic
---
## Alignment with the MCP Server Cards specification (SEP-2127)
This proposal is directly relevant to the active MCP specification work on
SEP-2127: MCP Server Cards (modelcontextprotocol/specification#2127),
which defines a standard for pre-connection server discovery via
`.well-known/mcp/server-card.json`.
Several open questions in SEP-2127 map precisely to patterns ALP already
implements in production:
| SEP-2127 open question | ALP v0.9.0 answer |
|---|---|
| Should `tools[]` be included in the Server Card? | ALP `tools[]` with `endpoint`, `input_schema`, `description` — static, opt-in, runtime-agnostic |
| How should dynamic vs. static primitives be handled? | ALP proxy mode: card declares static tool shapes; ALP Server forwards calls to existing HTTP endpoints — zero LLM-side ambiguity |
| What is the relationship between Server Card and Agent Card? | ALP `agent.alp.json` is the Agent Card — identity + persona + tools + memory in one artifact, served at `/agent` |
| How does pre-connection discovery work without `.well-known`? | ALP `server.alp.json` at server root + `AGENT_CARD_URL` env var for remote loading from GitHub raw URLs |
| Who hosts the Server Card if the repo owner doesn't control `.well-known`? | ALP remote card mode (v0.6.0): card lives in the GitHub repo, a hosted ALP Server reads it — no `.well-known` control needed |
The live ALP reference server at https://agent-load-protocol.onrender.com/mcp
already implements all of the above and is loadable today in any
MCP-compatible runtime. This makes `get_agent_card` not just a
GitHub-specific convenience tool, but a concrete early implementation of
the discovery pattern SEP-2127 is standardizing.
SEP-2127 was also linked to this issue by the specification maintainers,
confirming the connection between the two efforts.
---
## References
- ALP repository: https://github.com/RodrigoMvs123/agent-load-protocol
- ALP live MCP endpoint: https://agent-load-protocol.onrender.com/mcp
- ALP JSON schema: https://github.com/RodrigoMvs123/agent-load-protocol/blob/main/schema/agent.alp.schema.json
- ALP SPEC.md: https://github.com/RodrigoMvs123/agent-load-protocol/blob/main/SPEC.md
- ALP pip library (v0.7.0): `pip install alp-server`
- hello-agent-alp-kiro repo: https://github.com/RodrigoMvs123/hello-agent-alp-kiro
- hello-agent live agent card: https://hello-agent-alp-kiro.onrender.com/agent
- hello-agent live MCP endpoint: https://hello-agent-alp-kiro.onrender.com/mcp
コントリビューションガイド
評価
この issue はまだ評価されていません。