agenthive-mcp 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agenthive_mcp/__init__.py +3 -0
- agenthive_mcp/client.py +73 -0
- agenthive_mcp/server.py +183 -0
- agenthive_mcp-1.0.0.dist-info/METADATA +431 -0
- agenthive_mcp-1.0.0.dist-info/RECORD +9 -0
- agenthive_mcp-1.0.0.dist-info/WHEEL +5 -0
- agenthive_mcp-1.0.0.dist-info/entry_points.txt +2 -0
- agenthive_mcp-1.0.0.dist-info/licenses/LICENSE +21 -0
- agenthive_mcp-1.0.0.dist-info/top_level.txt +1 -0
agenthive_mcp/client.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Lazy-initialised AgentHive HTTP client.
|
|
2
|
+
|
|
3
|
+
Reads AGENTHIVE_URL/AGENTHIVE_TOKEN/AGENTHIVE_TEAM_ID from the environment
|
|
4
|
+
at call time (not import time), so importing this module never fails just
|
|
5
|
+
because env vars are unset - useful for tests, linting, and Docker image
|
|
6
|
+
builds, same reasoning as snyk-mcp's client.py.
|
|
7
|
+
|
|
8
|
+
Deliberately plain urllib rather than an SDK or httpx dependency: AgentHive
|
|
9
|
+
is a small first-party HTTP API (see polarpoint-io/agenthive's server.py),
|
|
10
|
+
not a large third-party surface worth a client library, and this repo's
|
|
11
|
+
whole point is staying a thin, dependency-light bridge (see ADR.md's "Why
|
|
12
|
+
not build an LLM-request proxy" in the main agenthive repo).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
import urllib.error
|
|
20
|
+
import urllib.parse
|
|
21
|
+
import urllib.request
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AgentHiveConfigError(RuntimeError):
|
|
25
|
+
"""Raised when required AGENTHIVE_* env vars are missing."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AgentHiveError(RuntimeError):
|
|
29
|
+
"""Raised on any non-2xx response from the AgentHive API, with the
|
|
30
|
+
server's own error message rather than a generic HTTP status."""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_config() -> tuple[str, str, str]:
|
|
34
|
+
"""Return (base_url, token, team_id) from the environment, or raise
|
|
35
|
+
AgentHiveConfigError naming exactly what's missing."""
|
|
36
|
+
missing = [
|
|
37
|
+
name for name in ("AGENTHIVE_URL", "AGENTHIVE_TOKEN", "AGENTHIVE_TEAM_ID")
|
|
38
|
+
if not os.environ.get(name)
|
|
39
|
+
]
|
|
40
|
+
if missing:
|
|
41
|
+
raise AgentHiveConfigError(
|
|
42
|
+
"agenthive-mcp is missing " + ", ".join(missing) + " - set these in "
|
|
43
|
+
"the MCP client config's env block (see README.md)."
|
|
44
|
+
)
|
|
45
|
+
return (
|
|
46
|
+
os.environ["AGENTHIVE_URL"].rstrip("/"),
|
|
47
|
+
os.environ["AGENTHIVE_TOKEN"],
|
|
48
|
+
os.environ["AGENTHIVE_TEAM_ID"],
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def request(method: str, path: str, body: dict | None = None, query: dict | None = None) -> dict:
|
|
53
|
+
"""A single AgentHive API call using the caller's personal token.
|
|
54
|
+
Every MCP tool in server.py is a thin pass-through to this."""
|
|
55
|
+
base_url, token, _ = get_config()
|
|
56
|
+
url = base_url + path
|
|
57
|
+
if query:
|
|
58
|
+
url += "?" + urllib.parse.urlencode(query)
|
|
59
|
+
data = json.dumps(body).encode("utf-8") if body is not None else None
|
|
60
|
+
req = urllib.request.Request(url, data=data, method=method)
|
|
61
|
+
req.add_header("X-API-Key", token)
|
|
62
|
+
req.add_header("Content-Type", "application/json")
|
|
63
|
+
try:
|
|
64
|
+
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
65
|
+
return json.loads(resp.read())
|
|
66
|
+
except urllib.error.HTTPError as e:
|
|
67
|
+
try:
|
|
68
|
+
detail = json.loads(e.read()).get("error", "unknown error")
|
|
69
|
+
except (json.JSONDecodeError, AttributeError):
|
|
70
|
+
detail = e.reason
|
|
71
|
+
raise AgentHiveError(f"{e.code}: {detail}") from None
|
|
72
|
+
except urllib.error.URLError as e:
|
|
73
|
+
raise AgentHiveError(f"could not reach {base_url}: {e.reason}") from None
|
agenthive_mcp/server.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""agenthive-mcp - a thin MCP (Model Context Protocol) server exposing
|
|
2
|
+
AgentHive's member-level calls - retrieve_context, log_session,
|
|
3
|
+
create_agent, list_agents, create_task, and list_tasks - as native tools
|
|
4
|
+
for Cursor, Claude Code, and any other MCP client.
|
|
5
|
+
|
|
6
|
+
This is deliberately a standalone, self-contained wrapper: it makes its
|
|
7
|
+
own plain HTTP calls to a running AgentHive service rather than importing
|
|
8
|
+
anything from the agenthive repo, so this repo has no dependency on that
|
|
9
|
+
one at build, install, or test time - only a runtime one, on the base URL
|
|
10
|
+
of a service you already have running (see
|
|
11
|
+
https://github.com/polarpoint-io/agenthive).
|
|
12
|
+
|
|
13
|
+
It holds no state and makes no decisions of its own - every tool call is
|
|
14
|
+
a pass-through to the AgentHive HTTP API using the caller's own personal
|
|
15
|
+
token from AGENTHIVE_TOKEN. The member/admin permission split and the
|
|
16
|
+
approval gate (a logged session starts PENDING until reviewed) are both
|
|
17
|
+
enforced entirely server-side; this process can do exactly what that
|
|
18
|
+
token already lets it do over the API directly, nothing more. See
|
|
19
|
+
AgentHive's ADR.md ("Why not build an LLM-request proxy" and
|
|
20
|
+
"Authentication") for the reasoning this follows.
|
|
21
|
+
|
|
22
|
+
Only [member]-role calls are exposed - the same tier retrieve_context and
|
|
23
|
+
log_session already sit at (see AgentHive's server.py route table).
|
|
24
|
+
Admin-only calls (list_pending/approve/reject, user management,
|
|
25
|
+
auto-approve rules) are deliberately left out: they exist to let a human
|
|
26
|
+
operate the review gate from the review UI or an admin script, and
|
|
27
|
+
turning them into agent-callable tools would let an agent approve or
|
|
28
|
+
reject its own (or another agent's) pending memory, which defeats the
|
|
29
|
+
point of the gate. See AgentHive's ADR.md for why that gate exists.
|
|
30
|
+
|
|
31
|
+
Transport selection (env vars), matching the rest of the org's MCP
|
|
32
|
+
servers (see polarpoint-io/snyk-mcp):
|
|
33
|
+
TRANSPORT=stdio (default) - MCP stdio transport, spawned by your IDE
|
|
34
|
+
TRANSPORT=http - SSE/HTTP transport on HTTP_HOST:HTTP_PORT
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
import logging
|
|
40
|
+
import os
|
|
41
|
+
|
|
42
|
+
from mcp.server.fastmcp import FastMCP
|
|
43
|
+
|
|
44
|
+
from .client import get_config as _get_config
|
|
45
|
+
from .client import request as _request
|
|
46
|
+
|
|
47
|
+
logger = logging.getLogger("agenthive_mcp")
|
|
48
|
+
|
|
49
|
+
mcp = FastMCP(
|
|
50
|
+
name="agenthive",
|
|
51
|
+
instructions=(
|
|
52
|
+
"Shared, reviewed memory for a team of coding agents. Call "
|
|
53
|
+
"retrieve_context before starting work and log_session once you're "
|
|
54
|
+
"done. Requires AGENTHIVE_URL/AGENTHIVE_TOKEN/AGENTHIVE_TEAM_ID env "
|
|
55
|
+
"vars set to your own personal AgentHive token."
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@mcp.tool()
|
|
61
|
+
def retrieve_context(anchor: str, hops: int = 2, hub_cutoff: int = 15) -> dict:
|
|
62
|
+
"""Retrieve a bounded neighborhood of this team's reviewed, approved
|
|
63
|
+
memory around a topic. Call this once at the start of a session,
|
|
64
|
+
before starting work, so you inherit what teammates already learned
|
|
65
|
+
instead of rediscovering it. `anchor` is the topic/title to search
|
|
66
|
+
around (e.g. "Postgres connection pool exhaustion"); `hops` bounds how
|
|
67
|
+
far the traversal spreads from it (default 2); `hub_cutoff` stops
|
|
68
|
+
traversal through overly-connected "hub" nodes so one popular node
|
|
69
|
+
doesn't pull in the whole graph. Returns a `neighborhood` list of
|
|
70
|
+
memory nodes plus `approx_tokens`, what folding them into context
|
|
71
|
+
would actually cost."""
|
|
72
|
+
_, _, team_id = _get_config()
|
|
73
|
+
return _request(
|
|
74
|
+
"GET", f"/teams/{team_id}/memory/retrieve",
|
|
75
|
+
query={"anchor": anchor, "hops": hops, "hub_cutoff": hub_cutoff},
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@mcp.tool()
|
|
80
|
+
def log_session(
|
|
81
|
+
title: str,
|
|
82
|
+
body: str,
|
|
83
|
+
tags: list[str] | None = None,
|
|
84
|
+
links: list[str] | None = None,
|
|
85
|
+
agent_id: str | None = None,
|
|
86
|
+
task_id: str | None = None,
|
|
87
|
+
) -> dict:
|
|
88
|
+
"""Log what happened this session as a memory node for the team to
|
|
89
|
+
reuse. Call this once at the end of a session that learned something
|
|
90
|
+
worth keeping - a root cause, a fix, a decision, a gotcha. The node
|
|
91
|
+
starts PENDING and is invisible to retrieve_context until an admin
|
|
92
|
+
approves it (or it matches an auto-approve rule) - this is a
|
|
93
|
+
deliberate review gate, not a bug. `title` is a short, searchable
|
|
94
|
+
summary (this is what future retrieve_context anchors match against);
|
|
95
|
+
`body` is the actual content; `tags` and `links` are optional and
|
|
96
|
+
help retrieval and review. `agent_id`/`task_id` are optional ids from
|
|
97
|
+
create_agent/create_task - attaching them lets an admin auto-approve
|
|
98
|
+
by agent (see create_auto_approve_rule, admin-only) and lets future
|
|
99
|
+
retrieval be scoped to a task."""
|
|
100
|
+
_, _, team_id = _get_config()
|
|
101
|
+
return _request(
|
|
102
|
+
"POST", f"/teams/{team_id}/memory",
|
|
103
|
+
body={
|
|
104
|
+
"title": title, "body": body, "tags": tags or [], "links": links or [],
|
|
105
|
+
"agent_id": agent_id, "task_id": task_id,
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@mcp.tool()
|
|
111
|
+
def create_agent(name: str, description: str = "", system_prompt: str = "") -> dict:
|
|
112
|
+
"""Register an agent identity with the team, so logged sessions can be
|
|
113
|
+
attributed to it (pass the returned id as log_session's `agent_id`)
|
|
114
|
+
and so an admin can target it with an auto-approve rule. `name` is
|
|
115
|
+
how it shows up in the review UI; `description` and `system_prompt`
|
|
116
|
+
are optional context for reviewers."""
|
|
117
|
+
_, _, team_id = _get_config()
|
|
118
|
+
return _request(
|
|
119
|
+
"POST", f"/teams/{team_id}/agents",
|
|
120
|
+
body={"name": name, "description": description, "system_prompt": system_prompt},
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@mcp.tool()
|
|
125
|
+
def list_agents() -> dict:
|
|
126
|
+
"""List the agent identities already registered with this team, e.g.
|
|
127
|
+
to find an existing agent's id instead of creating a duplicate with
|
|
128
|
+
create_agent."""
|
|
129
|
+
_, _, team_id = _get_config()
|
|
130
|
+
return _request("GET", f"/teams/{team_id}/agents")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@mcp.tool()
|
|
134
|
+
def create_task(name: str, description: str = "") -> dict:
|
|
135
|
+
"""Register a task with the team, so logged sessions can be scoped to
|
|
136
|
+
it (pass the returned id as log_session's `task_id`) - useful when
|
|
137
|
+
several sessions across one piece of work should be filterable
|
|
138
|
+
together later. `name` is how it shows up in the review UI;
|
|
139
|
+
`description` is optional context."""
|
|
140
|
+
_, _, team_id = _get_config()
|
|
141
|
+
return _request(
|
|
142
|
+
"POST", f"/teams/{team_id}/tasks",
|
|
143
|
+
body={"name": name, "description": description},
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@mcp.tool()
|
|
148
|
+
def list_tasks() -> dict:
|
|
149
|
+
"""List the tasks already registered with this team, e.g. to find an
|
|
150
|
+
existing task's id instead of creating a duplicate with create_task."""
|
|
151
|
+
_, _, team_id = _get_config()
|
|
152
|
+
return _request("GET", f"/teams/{team_id}/tasks")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# ---------------------------------------------------------------------------
|
|
156
|
+
# Entrypoint
|
|
157
|
+
# ---------------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
def main() -> None:
|
|
160
|
+
"""Console entrypoint. Selects transport based on TRANSPORT env var,
|
|
161
|
+
same convention as the rest of the org's MCP servers."""
|
|
162
|
+
logging.basicConfig(
|
|
163
|
+
level=os.environ.get("LOG_LEVEL", "INFO").upper(),
|
|
164
|
+
format="%(asctime)s %(levelname)s %(name)s %(message)s",
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
transport = os.environ.get("TRANSPORT", "stdio").lower()
|
|
168
|
+
if transport == "stdio":
|
|
169
|
+
logger.info("Starting agenthive-mcp on stdio transport")
|
|
170
|
+
mcp.run(transport="stdio")
|
|
171
|
+
elif transport in ("http", "sse"):
|
|
172
|
+
host = os.environ.get("HTTP_HOST", "0.0.0.0")
|
|
173
|
+
port = int(os.environ.get("HTTP_PORT", "8000"))
|
|
174
|
+
mcp.settings.host = host
|
|
175
|
+
mcp.settings.port = port
|
|
176
|
+
logger.info("Starting agenthive-mcp on SSE transport at %s:%d", host, port)
|
|
177
|
+
mcp.run(transport="sse")
|
|
178
|
+
else:
|
|
179
|
+
raise SystemExit(f"Unknown TRANSPORT={transport!r}. Use 'stdio' or 'http'.")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if __name__ == "__main__":
|
|
183
|
+
main()
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agenthive-mcp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: MCP server exposing AgentHive's shared team memory as native tools for Cursor and Claude Code
|
|
5
|
+
Author: Surj Bains
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Surj Bains
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/polarpoint-io/agenthive-mcp
|
|
29
|
+
Project-URL: AgentHive, https://github.com/polarpoint-io/agenthive
|
|
30
|
+
Keywords: mcp,agenthive,memory,coding-agents,platform-engineering
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Requires-Python: >=3.10
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
License-File: LICENSE
|
|
41
|
+
Requires-Dist: mcp<2,>=1.2.0
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
44
|
+
Requires-Dist: anyio>=4.0; extra == "dev"
|
|
45
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
46
|
+
Dynamic: license-file
|
|
47
|
+
|
|
48
|
+
# agenthive-mcp
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
[](https://github.com/polarpoint-io/agenthive-mcp/actions/workflows/ci.yml)
|
|
53
|
+
[](LICENSE)
|
|
54
|
+
|
|
55
|
+
A Model Context Protocol (MCP) server that exposes [AgentHive](https://github.com/polarpoint-io/agenthive)'s shared, reviewed team memory to LLM clients (Claude Desktop, Claude Code, Cursor, VS Code, etc.) - `retrieve_context`, `log_session`, `create_agent`, `list_agents`, `create_task`, and `list_tasks` as native tools, instead of a `CLAUDE.md` / `.cursor/rules` instruction block that calls AgentHive's HTTP API by hand.
|
|
56
|
+
|
|
57
|
+
> **PyPI**: `pip install agenthive-mcp` · **Image**: `ghcr.io/polarpoint-io/agenthive-mcp:latest` · **Repo**: <https://github.com/polarpoint-io/agenthive-mcp>
|
|
58
|
+
|
|
59
|
+
## Table of contents
|
|
60
|
+
|
|
61
|
+
- [Quick start](#quick-start)
|
|
62
|
+
- [Configuration](#configuration)
|
|
63
|
+
- [Client integrations](#client-integrations)
|
|
64
|
+
- [Tool reference](#tool-reference)
|
|
65
|
+
- [Wiring an agent up to actually use these tools](#wiring-an-agent-up-to-actually-use-these-tools)
|
|
66
|
+
- [Why a separate repo from AgentHive](#why-a-separate-repo-from-agenthive)
|
|
67
|
+
- [Running from source](#running-from-source)
|
|
68
|
+
- [Development](#development)
|
|
69
|
+
- [Publishing](#publishing)
|
|
70
|
+
- [Security notes](#security-notes)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## Quick start
|
|
74
|
+
|
|
75
|
+
You need an AgentHive team and a personal token first - see [AgentHive's onboarding guide](https://github.com/polarpoint-io/agenthive/blob/main/ONBOARDING.md) if you don't have one yet.
|
|
76
|
+
|
|
77
|
+
### 1. pip (no Docker)
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install agenthive-mcp
|
|
81
|
+
export AGENTHIVE_URL=https://your-agenthive-host
|
|
82
|
+
export AGENTHIVE_TOKEN=your_personal_token
|
|
83
|
+
export AGENTHIVE_TEAM_ID=your_team_id
|
|
84
|
+
|
|
85
|
+
agenthive-mcp # stdio
|
|
86
|
+
TRANSPORT=http HTTP_PORT=8000 agenthive-mcp # HTTP/SSE
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 2. Docker (stdio — launched by your MCP client)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
docker pull ghcr.io/polarpoint-io/agenthive-mcp:latest
|
|
93
|
+
|
|
94
|
+
docker run --rm -i \
|
|
95
|
+
-e AGENTHIVE_URL=https://your-agenthive-host \
|
|
96
|
+
-e AGENTHIVE_TOKEN=your_personal_token \
|
|
97
|
+
-e AGENTHIVE_TEAM_ID=your_team_id \
|
|
98
|
+
ghcr.io/polarpoint-io/agenthive-mcp:latest
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 3. Docker (HTTP/SSE — standalone service)
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
docker run --rm \
|
|
105
|
+
-p 8000:8000 \
|
|
106
|
+
-e AGENTHIVE_URL=https://your-agenthive-host \
|
|
107
|
+
-e AGENTHIVE_TOKEN=your_personal_token \
|
|
108
|
+
-e AGENTHIVE_TEAM_ID=your_team_id \
|
|
109
|
+
-e TRANSPORT=http \
|
|
110
|
+
ghcr.io/polarpoint-io/agenthive-mcp:latest
|
|
111
|
+
# SSE endpoint: http://localhost:8000/sse
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Use your own token, not a shared or admin one - whatever it can do (`member` or `admin`) is what this server can do on your behalf, nothing more or less (see [Security notes](#security-notes)).
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
## Configuration
|
|
118
|
+
|
|
119
|
+
| Variable | Required | Default | Description |
|
|
120
|
+
|---|---|---|---|
|
|
121
|
+
| `AGENTHIVE_URL` | yes | — | Base URL of a running AgentHive service |
|
|
122
|
+
| `AGENTHIVE_TOKEN` | yes | — | Your personal AgentHive token |
|
|
123
|
+
| `AGENTHIVE_TEAM_ID` | yes | — | Your AgentHive team id |
|
|
124
|
+
| `TRANSPORT` | no | `stdio` | `stdio` or `http` |
|
|
125
|
+
| `HTTP_HOST` | no | `0.0.0.0` | Bind host (HTTP mode) |
|
|
126
|
+
| `HTTP_PORT` | no | `8000` | Bind port (HTTP mode) |
|
|
127
|
+
| `LOG_LEVEL` | no | `INFO` | Python log level |
|
|
128
|
+
|
|
129
|
+
See [`.env.example`](.env.example) for a copy-pasteable template.
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
## Client integrations
|
|
133
|
+
|
|
134
|
+
Each client supports two transport options — **pip** (recommended, no Docker required) or **Docker**.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Install once
|
|
138
|
+
pip install agenthive-mcp
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### Claude Desktop
|
|
144
|
+
|
|
145
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows).
|
|
146
|
+
|
|
147
|
+
**pip (recommended)**
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"mcpServers": {
|
|
151
|
+
"agenthive": {
|
|
152
|
+
"command": "agenthive-mcp",
|
|
153
|
+
"env": {
|
|
154
|
+
"AGENTHIVE_URL": "https://your-agenthive-host",
|
|
155
|
+
"AGENTHIVE_TOKEN": "your_personal_token",
|
|
156
|
+
"AGENTHIVE_TEAM_ID": "your_team_id"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Docker**
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"mcpServers": {
|
|
167
|
+
"agenthive": {
|
|
168
|
+
"command": "docker",
|
|
169
|
+
"args": [
|
|
170
|
+
"run", "--rm", "-i",
|
|
171
|
+
"-e", "AGENTHIVE_URL", "-e", "AGENTHIVE_TOKEN", "-e", "AGENTHIVE_TEAM_ID",
|
|
172
|
+
"ghcr.io/polarpoint-io/agenthive-mcp:latest"
|
|
173
|
+
],
|
|
174
|
+
"env": {
|
|
175
|
+
"AGENTHIVE_URL": "https://your-agenthive-host",
|
|
176
|
+
"AGENTHIVE_TOKEN": "your_personal_token",
|
|
177
|
+
"AGENTHIVE_TEAM_ID": "your_team_id"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Restart Claude Desktop after editing. You should see a hammer icon in the chat confirming the `agenthive` server is connected with all 6 tools available.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### Claude Code
|
|
189
|
+
|
|
190
|
+
**pip (recommended)**
|
|
191
|
+
```bash
|
|
192
|
+
pip install agenthive-mcp
|
|
193
|
+
|
|
194
|
+
claude mcp add agenthive -- agenthive-mcp
|
|
195
|
+
# then export your config before running claude:
|
|
196
|
+
export AGENTHIVE_URL=https://your-agenthive-host
|
|
197
|
+
export AGENTHIVE_TOKEN=your_personal_token
|
|
198
|
+
export AGENTHIVE_TEAM_ID=your_team_id
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Docker**
|
|
202
|
+
```bash
|
|
203
|
+
claude mcp add agenthive -- docker run --rm -i \
|
|
204
|
+
-e AGENTHIVE_URL -e AGENTHIVE_TOKEN -e AGENTHIVE_TEAM_ID \
|
|
205
|
+
ghcr.io/polarpoint-io/agenthive-mcp:latest
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Or a plain `.mcp.json` in the repo root works too - same shape as Claude Desktop's config above.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Cursor
|
|
213
|
+
|
|
214
|
+
Edit `~/.cursor/mcp.json`:
|
|
215
|
+
|
|
216
|
+
**pip (recommended)**
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"mcpServers": {
|
|
220
|
+
"agenthive": {
|
|
221
|
+
"command": "agenthive-mcp",
|
|
222
|
+
"env": {
|
|
223
|
+
"AGENTHIVE_URL": "https://your-agenthive-host",
|
|
224
|
+
"AGENTHIVE_TOKEN": "your_personal_token",
|
|
225
|
+
"AGENTHIVE_TEAM_ID": "your_team_id"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Docker**
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"mcpServers": {
|
|
236
|
+
"agenthive": {
|
|
237
|
+
"command": "docker",
|
|
238
|
+
"args": ["run", "--rm", "-i",
|
|
239
|
+
"-e", "AGENTHIVE_URL", "-e", "AGENTHIVE_TOKEN", "-e", "AGENTHIVE_TEAM_ID",
|
|
240
|
+
"ghcr.io/polarpoint-io/agenthive-mcp:latest"],
|
|
241
|
+
"env": {
|
|
242
|
+
"AGENTHIVE_URL": "https://your-agenthive-host",
|
|
243
|
+
"AGENTHIVE_TOKEN": "your_personal_token",
|
|
244
|
+
"AGENTHIVE_TEAM_ID": "your_team_id"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### VS Code (Continue)
|
|
254
|
+
|
|
255
|
+
Edit `~/.continue/config.json`:
|
|
256
|
+
|
|
257
|
+
**pip (recommended)**
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"mcpServers": [{
|
|
261
|
+
"name": "agenthive",
|
|
262
|
+
"command": "agenthive-mcp",
|
|
263
|
+
"env": {
|
|
264
|
+
"AGENTHIVE_URL": "https://your-agenthive-host",
|
|
265
|
+
"AGENTHIVE_TOKEN": "your_personal_token",
|
|
266
|
+
"AGENTHIVE_TEAM_ID": "your_team_id"
|
|
267
|
+
}
|
|
268
|
+
}]
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
### HTTP / SSE (remote or shared server)
|
|
275
|
+
|
|
276
|
+
If you prefer to run the server as a persistent HTTP service rather than a subprocess - still bound to whichever token you start it with, this is a transport choice, not a different auth model:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
# pip
|
|
280
|
+
pip install agenthive-mcp
|
|
281
|
+
AGENTHIVE_URL=... AGENTHIVE_TOKEN=... AGENTHIVE_TEAM_ID=... TRANSPORT=http HTTP_PORT=8000 agenthive-mcp
|
|
282
|
+
|
|
283
|
+
# Docker
|
|
284
|
+
docker run --rm -p 8000:8000 \
|
|
285
|
+
-e AGENTHIVE_URL=... -e AGENTHIVE_TOKEN=... -e AGENTHIVE_TEAM_ID=... \
|
|
286
|
+
-e TRANSPORT=http \
|
|
287
|
+
ghcr.io/polarpoint-io/agenthive-mcp:latest
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Then point your MCP client at `http://localhost:8000/sse`.
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
## Tool reference
|
|
294
|
+
|
|
295
|
+
Every tool here is a **member**-role AgentHive call - the same tier your personal token already grants over the API directly. Admin-only calls (`list_pending`/`approve`/`reject`, user management, auto-approve rules) are deliberately not exposed as tools: they exist so a *human* operates the review gate from the review UI or an admin script, and turning them into agent-callable tools would let an agent approve or reject its own pending memory, which defeats the point of the gate. See AgentHive's `ADR.md` for why the gate exists, and its README for those calls.
|
|
296
|
+
|
|
297
|
+
| Tool | Description |
|
|
298
|
+
|---|---|
|
|
299
|
+
| `retrieve_context` | Bounded neighborhood of this team's reviewed, approved memory around a topic (`anchor`, `hops=2`, `hub_cutoff=15`) |
|
|
300
|
+
| `log_session` | Log what happened this session as a memory node (`title`, `body`, `tags`, `links`, `agent_id`, `task_id`) - starts `pending` |
|
|
301
|
+
| `create_agent` | Register an agent identity (`name`, `description`, `system_prompt`) so sessions can be attributed to it |
|
|
302
|
+
| `list_agents` | List agent identities already registered with the team |
|
|
303
|
+
| `create_task` | Register a task (`name`, `description`) so sessions can be scoped to it |
|
|
304
|
+
| `list_tasks` | List tasks already registered with the team |
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
## Wiring an agent up to actually use these tools
|
|
308
|
+
|
|
309
|
+
Tools existing in the tool list doesn't make an agent call them unprompted - it needs a line telling it when.
|
|
310
|
+
|
|
311
|
+
If the repo uses polarpoint-io's platform-standards `AGENTS.md` template (see [`ai-capabilities/platform-standards/templates/default-agents-md.md`](https://github.com/polarpoint-io/ai-capabilities/blob/main/platform-standards/templates/default-agents-md.md)), add it to **Zone 3** ("Repo-specific notes" - free, team-owned, and explicitly meant for "context about the domain, gotchas, preferred libraries, links to runbooks"):
|
|
312
|
+
|
|
313
|
+
```markdown
|
|
314
|
+
## AgentHive
|
|
315
|
+
|
|
316
|
+
Before starting work, call `retrieve_context` with a short description of
|
|
317
|
+
the task. When you're done, call `log_session` summarizing what you did
|
|
318
|
+
and learned.
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Team-specific conventions (which tags to use, the team's `AGENTHIVE_TEAM_ID`) belong in Zone 2 instead - guarded, but team-owned, meant to extend Zone 1 rather than override it. Don't put either in Zone 1: that's platform-locked, and making AgentHive retrieval mandatory org-wide is a bigger call than one repo should make on its own - it would need a PR to `ai-capabilities` and platform-team review.
|
|
322
|
+
|
|
323
|
+
Repos without that template yet can use a plain `CLAUDE.md` / `.cursor/rules` line instead - same content, just a different file.
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
## Why a separate repo from AgentHive
|
|
327
|
+
|
|
328
|
+
This started as a module inside the AgentHive repo itself, then moved out: it has its own dependency (`mcp`), its own release cadence (an IDE integration changes on its own schedule, unrelated to the service's), and no reason to need AgentHive's own container image, Helm chart, or CI matrix rebuilt every time it changes - or vice versa.
|
|
329
|
+
|
|
330
|
+
It's self-contained: it makes its own plain HTTP calls to a running AgentHive service rather than importing anything from the `agenthive` repo, so this repo has no dependency on that one at build, install, or test time - only a runtime one, on the base URL of a service you already have running.
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
## Running from source
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
git clone git@github.com:polarpoint-io/agenthive-mcp.git
|
|
337
|
+
cd agenthive-mcp
|
|
338
|
+
python -m venv .venv && source .venv/bin/activate
|
|
339
|
+
pip install -e .[dev]
|
|
340
|
+
|
|
341
|
+
export AGENTHIVE_URL=...
|
|
342
|
+
export AGENTHIVE_TOKEN=...
|
|
343
|
+
export AGENTHIVE_TEAM_ID=...
|
|
344
|
+
|
|
345
|
+
agenthive-mcp # stdio
|
|
346
|
+
TRANSPORT=http HTTP_PORT=8000 agenthive-mcp # HTTP/SSE
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Or via the Makefile:
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
make dev # install with dev extras
|
|
353
|
+
make test # pytest
|
|
354
|
+
make lint # ruff check
|
|
355
|
+
make run # stdio
|
|
356
|
+
make run-http # HTTP/SSE on :8000
|
|
357
|
+
make docker # build the image locally
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
## Development
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
make dev
|
|
365
|
+
make test
|
|
366
|
+
make lint
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
The test suite (`tests/test_tools.py`) drives the server as a real subprocess over real MCP stdio, using a real `mcp.ClientSession` - nothing mocked at the protocol layer. The AgentHive side is a small local fake (`tests/fake_agenthive.py`), not the real service, since this repo shouldn't need AgentHive itself checked out to test its own HTTP plumbing; AgentHive's own approval-gate/retrieval/auth behavior is already covered by its own test suite, in its own repo, against the real `server.py`. Try this server against a real AgentHive instance manually if you want to confirm the whole chain end to end.
|
|
370
|
+
|
|
371
|
+
Adding a new tool:
|
|
372
|
+
|
|
373
|
+
1. Add a `@mcp.tool()` function in `src/agenthive_mcp/server.py`, calling `_request()` from `client.py`. Only for a **member**-role AgentHive endpoint - see [Tool reference](#tool-reference).
|
|
374
|
+
2. Add a matching route to `tests/fake_agenthive.py` if the endpoint isn't already covered.
|
|
375
|
+
3. Add a test in `tests/test_tools.py` using the existing `stdio_client`/`ClientSession` pattern.
|
|
376
|
+
|
|
377
|
+
See [`AGENTS.md`](AGENTS.md) for deeper contribution guidance.
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
## Publishing
|
|
381
|
+
|
|
382
|
+
Releases are fully automated via [semantic-release](https://semantic-release.gitbook.io/) - no manual tagging needed.
|
|
383
|
+
|
|
384
|
+
### How it works
|
|
385
|
+
|
|
386
|
+
Every push to `main` runs the CI pipeline:
|
|
387
|
+
|
|
388
|
+
1. **Test** — lint (`ruff`) + pytest across Python 3.10 / 3.11 / 3.12
|
|
389
|
+
2. **Docker** — builds and pushes the image to GHCR
|
|
390
|
+
3. **Release** — semantic-release analyses conventional commits, bumps the version, updates `CHANGELOG.md`, publishes to PyPI, and creates a GitHub Release
|
|
391
|
+
|
|
392
|
+
A release only happens when commits contain a `feat:`, `fix:`, or breaking-change - `chore:`, `docs:`, `ci:` commits don't trigger one.
|
|
393
|
+
|
|
394
|
+
### Docker image tags
|
|
395
|
+
|
|
396
|
+
| Tag | When pushed |
|
|
397
|
+
|---|---|
|
|
398
|
+
| `latest` | Every merge to `main` |
|
|
399
|
+
| `sha-<short>` | Every merge to `main` |
|
|
400
|
+
| `1.2.3` / `1.2` | On a semantic-release version bump |
|
|
401
|
+
|
|
402
|
+
### Required GitHub secrets
|
|
403
|
+
|
|
404
|
+
| Secret | Description |
|
|
405
|
+
|---|---|
|
|
406
|
+
| `POL_GH_TOKEN` | Personal access token with `repo` + `write:packages` scope |
|
|
407
|
+
| `PYPI_TOKEN` | PyPI API token for the `agenthive-mcp` project |
|
|
408
|
+
|
|
409
|
+
Add both at: **GitHub repo → Settings → Secrets and variables → Actions**.
|
|
410
|
+
|
|
411
|
+
### Commit conventions
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
feat: add new tool → minor version bump (0.x.0)
|
|
415
|
+
fix: correct response shape → patch bump (0.0.x)
|
|
416
|
+
feat!: breaking change → major bump (x.0.0)
|
|
417
|
+
chore/docs/ci/test → no release
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
## Security notes
|
|
422
|
+
|
|
423
|
+
- The container runs as a non-root user (`uid 10001`).
|
|
424
|
+
- `AGENTHIVE_TOKEN` is read from env vars only - never written to disk.
|
|
425
|
+
- This process holds no state and makes no decisions of its own - every tool call is a pass-through to AgentHive's HTTP API using the caller's own token. It can do exactly what that token already lets it do over the API directly, nothing more.
|
|
426
|
+
- Admin-only calls (the review gate, user management, auto-approve rules) are deliberately **not** exposed as tools - see [Tool reference](#tool-reference).
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
## License
|
|
430
|
+
|
|
431
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
agenthive_mcp/__init__.py,sha256=s7GSsGyfBQfN0zUQdL9AcwGv-AvruCN8PWZZaGyGRoU,103
|
|
2
|
+
agenthive_mcp/client.py,sha256=UqRhRLNtQjYVGk14sYJHTd99LeDUG_qHlx5gJy5FnDM,2863
|
|
3
|
+
agenthive_mcp/server.py,sha256=gNx0z8UrD6wHojC-N9dAmq6hUIqrtKzjzUP6HZJlpJc,7713
|
|
4
|
+
agenthive_mcp-1.0.0.dist-info/licenses/LICENSE,sha256=tzIxURH0v71uEMtkuuEZu45QTT-kNRh6xveRCsxVh-E,1067
|
|
5
|
+
agenthive_mcp-1.0.0.dist-info/METADATA,sha256=Btt0eTBMhlDdeDi6Kiy3zN6qPLcz9FKCnc5fBBSQQVE,16144
|
|
6
|
+
agenthive_mcp-1.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
7
|
+
agenthive_mcp-1.0.0.dist-info/entry_points.txt,sha256=w3H2dzh-_Zyxq64EXmVLm-TKV6lCCdsz8Y3ZW4W65bc,60
|
|
8
|
+
agenthive_mcp-1.0.0.dist-info/top_level.txt,sha256=48SkxM4krxsU7cdWwUMObOUqKAznIFrHURzz_a1CkQw,14
|
|
9
|
+
agenthive_mcp-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Surj Bains
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
agenthive_mcp
|