Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,114 @@ Responses use `Cache-Control: no-store` and `Content-Type: application/json; cha

---

## JSON-RPC MCP endpoint (spec-compatible)

In addition to the **`/mcp`** HTTP interface above, Scrumboy exposes a Model Context Protocol (MCP) oriented endpoint that speaks **JSON-RPC 2.0**. This is a **separate** transport from the legacy `{ "tool", "input" }` POST body; both are mounted on the same MCP adapter.

**Endpoint:** `POST /mcp/rpc` (trailing slash `/mcp/rpc/` is accepted).

**Intended use:** MCP-style clients (e.g. Claude Desktop, agent frameworks) that expect JSON-RPC framing.

### Protocol

- Uses **JSON-RPC 2.0**.
- **`jsonrpc`:** must be the string `"2.0"`.
- **`method`:** required (string).
- **`id`:** required for **requests** that expect a JSON body (`initialize`, `tools/list`, `tools/call`). Omitted for **notifications** (see below). For **parse errors**, the response uses `"id": null` per JSON-RPC.
- **`params`:** optional for `initialize` and `tools/list` (may be omitted or an object). For **`tools/call`**, `params` must be a JSON object (see below).

**Non-POST** requests receive a JSON-RPC error (`id` null). **HTTP status** for normal JSON-RPC replies is **200** for both success and error objects in the body (errors are not signaled only by HTTP status). The **`notifications/initialized`** (or **`initialized`**) notification is answered with **204 No Content** and an empty body.

**Example request:**

```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {}
}
```

### Supported methods

**`initialize`** — Initial handshake. Requires `id`. Returns `protocolVersion` (currently `2024-11-05`), `capabilities`, `serverInfo`, and optional `instructions`. `params` may be omitted or empty.

**`notifications/initialized`** or **`initialized`** — Client acknowledgment after `initialize`. Must be sent **without** `id` (notification). Server responds with **204** and no JSON body. If an `id` is present, the server rejects the call.

**`tools/list`** — Requires `id`. Returns `{ "tools": [ ... ] }`. Each entry has `name`, `description`, and `inputSchema` (JSON Schema object). **Today** the list includes **four** tools with full schemas (`projects.list`, `todos.create`, `todos.get`, `todos.update`); more entries will be added over time. **`tools/list` does not require a prior `initialize`.**

**`tools/call`** — Invokes a tool by name. Requires `id` and a **`params` object** containing:

- **`name`** (string, required): exact registered tool name (same names as `POST /mcp`’s `tool` field).
- **`arguments`** (object, optional): tool input; if omitted, treated as `{}`.

**`tools/call` uses the same tool registry as `POST /mcp`**, so any implemented tool may be invoked even if it does not yet appear in `tools/list`. For tools that **do** appear in `tools/list`, the server performs a **lightweight check** that JSON Schema `required` top-level properties are present in `arguments` before calling the handler; full JSON Schema validation is not performed. Unknown tool names yield JSON-RPC **`method not found`** (`-32601`); optional `error.data` may include `{ "name": "<tool>" }`.

**Example `tools/call`:**

```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "todos.create",
"arguments": {
"projectSlug": "my-project",
"title": "New todo"
}
}
}
```

### Response format

All JSON-RPC **responses with a body** include `"jsonrpc": "2.0"` and preserve the request `id` (except parse errors → `id: null`). This endpoint **does not** use the legacy `ok` / `data` / `meta` envelope.

**Success (`tools/call` result shape):**

```json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "json",
"json": {}
}
]
}
}
```

The `json` object is the tool’s result value (same conceptual payload as legacy `data`, including nested shapes such as `{ "todo": { ... } }` where the tool returns that).

**Error:**

```json
{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32602,
"message": "invalid params"
}
}
```

**Typical JSON-RPC error codes:** `-32700` parse error, `-32600` invalid request, `-32601` method/tool not found, `-32602` invalid params / validation, `-32603` internal error. The `message` string is human-readable; some errors include optional `data`.

### Notes

- **Stateless HTTP:** there is no server-side session between requests; behavior does not depend on having called `initialize` first for `tools/list` or `tools/call`.
- **`initialize` is supported** for clients that expect the handshake; it is **not** enforced before discovery or tool calls on this server.
- **Authentication** follows the same rules as **`/mcp`** (session cookie and Bearer token in `full` mode; anonymous mode boundary unchanged). See [Authentication and capability model](#authentication-and-capability-model).
- The **legacy `GET` / `POST /mcp`** endpoint remains **unchanged** and is documented in the sections above.

---

## Response envelopes

### Success
Expand Down
28 changes: 27 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
# Changelog

> **Upgrades:** No breaking changes in **3.7.x** unless noted below.
> **Upgrades:** No breaking changes in **3.7.x** / **3.8.x** unless noted below.


## [3.8.0] - 2026-04-03

### Features

- **MCP JSON-RPC: `tools/list` and `tools/call`** on **`POST /mcp/rpc`** — Completes the spec-oriented MCP loop alongside existing **`initialize`** / **`notifications/initialized`**. **`tools/list`** returns tools with **`name`**, **`description`**, and **`inputSchema`** (JSON Schema with **`required`** and tight objects where defined); the catalog starts with four tools (**`projects.list`**, **`todos.create`**, **`todos.get`**, **`todos.update`**) and will grow over time. **`tools/call`** accepts **`params.name`** and **`params.arguments`**, reuses the same tool handlers as legacy **`POST /mcp`**, and returns success as **`result.content[]`** with **`type: "json"`** and the tool payload in **`json`**. Discovery and invocation are **stateless** (no **`initialize`** required for **`tools/list`** or **`tools/call`**). Errors use JSON-RPC codes (**`-32601`** unknown tool, **`-32602`** invalid params / validation, **`-32603`** internal); unknown tools may include **`error.data`** with **`name`**.

### Improvements

- **Catalog `required` handling** — Pre-call checks read the **`required`** array whether it is stored as **`[]string`** (in-memory catalog) or **`[]any`** (e.g. after JSON round-trip), avoiding silent skips.
- **`tools/call` shape errors** — Clearer **`missing params`** / **`missing params.name`** messages for invalid requests.

### Documentation

- **`API.md`** — New **JSON-RPC MCP endpoint (spec-compatible)** section for **`POST /mcp/rpc`**: protocol rules, supported methods, response shapes, auth (same as **`/mcp`**), and how this differs from the legacy **`/mcp`** envelope.
- **`README.md`** — **MCP (JSON-RPC) for AI agents** subsection with **`curl`** examples (**`initialize`**, **`tools/list`**, **`tools/call`**), pointer to **`API.md`**, and notes on HTTP JSON-RPC vs stdio MCP clients.

---

## [3.7.8] - 2026-04-03

### Features

- **MCP JSON-RPC (Phase 1)** - New **`POST /mcp/rpc`** endpoint using **JSON-RPC 2.0** alongside the existing **`/mcp`** `{ "tool", "input" }` API (unchanged). Supports **`initialize`** (protocol version **2024-11-05**, `capabilities.tools`, `serverInfo`), **`notifications/initialized`** and **`initialized`** as notifications (**204** empty body), and spec error codes (e.g. **-32601** method not found). **`tools/list`** and **`tools/call`** added in **3.8.0**.

---

## [3.7.7] - 2026-04-03

### Features
Expand Down
61 changes: 56 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<p align="center">
<img width="372" src="internal/httpapi/web/githublogo.png" alt="scrumboy logo" />
<br />
<img src="https://img.shields.io/badge/version-v3.7.7-blue" alt="version" />
<img src="https://img.shields.io/badge/version-v3.8.0-blue" alt="version" />
<a href="LICENSE">
<img src="https://img.shields.io/badge/license-AGPL--v3-orange" alt="license" />
</a>
</p>

#### Self-hosted project management & issue-tracking solution + instant shareable & customizable boards + realtime collaboration, automation, API access and MCP support
#### Self-hosted project management & issue-tracking solution + instant shareable & customizable boards + realtime collaboration, automation, API access and MCP-compatible client support


<img width="2975" height="1078" alt="image" src="internal/httpapi/web/github_preview.jpg" />
Expand Down Expand Up @@ -116,9 +116,9 @@ Simplicity of a light Kanban, with the power of structured systems: Roles, sprin

## Integrations & API Access

Scrumboy supports API access tokens for automation, integrations, and AI agents.
Scrumboy supports API access tokens for automation, integrations, and programmatic MCP access (legacy HTTP and JSON-RPC — see below).

You can create a token from the API and use it to call MCP directly — no browser session or cookies required.
You can create a token from the API and use it to call MCP endpoints directly — no browser session or cookies required.

**Create a token (requires login session):**

Expand All @@ -139,11 +139,62 @@ curl -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer sb_your_token_here" \
-d '{"tool":"projects.list","input":{}}'
```

### MCP (JSON-RPC) for AI agents

Scrumboy exposes a **Model Context Protocol (MCP) compatible JSON-RPC endpoint** for AI agents (Claude, etc.) and MCP-compatible clients.

**Endpoint:** `POST /mcp/rpc`

This is separate from the `/mcp` HTTP endpoint above and follows **JSON-RPC 2.0** (`initialize`, `tools/list`, `tools/call`, etc.). See [`API.md`](API.md) for full detail.

#### Example: `initialize`

```bash
curl -X POST http://localhost:8080/mcp/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
```

#### Example: list tools

```bash
curl -X POST http://localhost:8080/mcp/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

#### Example: call a tool

```bash
curl -X POST http://localhost:8080/mcp/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sb_your_token_here" \
-d '{
"jsonrpc":"2.0",
"id":3,
"method":"tools/call",
"params":{
"name":"todos.create",
"arguments":{
"projectSlug":"my-project",
"title":"Created via MCP"
}
}
}'
```

**Notes**

- Compatible with MCP clients that support **HTTP JSON-RPC** to this URL.
- Some MCP clients expect **stdio**-based servers — those are **not** supported here.
- Authentication works via **session cookie** or **Bearer** token (same rules as `/mcp`).

This enables:

- CLI usage
- CI/CD automation
- AI agents (Claude, etc.)
- AI agents and MCP clients (use **`POST /mcp/rpc`** for JSON-RPC; **`POST /mcp`** remains available for the legacy `{ "tool", "input" }` envelope)
- Scripting/integrations without login flows


Expand Down
5 changes: 5 additions & 0 deletions internal/mcp/http_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ func (a *Adapter) resolveAndValidateAuth(w http.ResponseWriter, r *http.Request)
func (a *Adapter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-store")

if r.URL.Path == "/mcp/rpc" || r.URL.Path == "/mcp/rpc/" {
a.serveJSONRPC(w, r)
return
}

if r.URL.Path != "/mcp" && r.URL.Path != "/mcp/" {
writeError(w, newAdapterError(http.StatusNotFound, CodeNotFound, "not found", nil))
return
Expand Down
Loading
Loading