govql-mcp-server 0.1.0__tar.gz
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.
- govql_mcp_server-0.1.0/.env +8 -0
- govql_mcp_server-0.1.0/.gitignore +9 -0
- govql_mcp_server-0.1.0/.python-version +1 -0
- govql_mcp_server-0.1.0/CHANGELOG.md +25 -0
- govql_mcp_server-0.1.0/CONTRIBUTING.md +51 -0
- govql_mcp_server-0.1.0/LICENSE +21 -0
- govql_mcp_server-0.1.0/PKG-INFO +137 -0
- govql_mcp_server-0.1.0/README.md +116 -0
- govql_mcp_server-0.1.0/RELEASE.md +242 -0
- govql_mcp_server-0.1.0/docs/design.md +93 -0
- govql_mcp_server-0.1.0/pyproject.toml +47 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/__init__.py +3 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/__main__.py +17 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/graphql_client.py +86 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/logger.py +14 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/server.py +17 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/tools/__init__.py +0 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/tools/_discovery_shared.py +47 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/tools/describe_type.py +100 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/tools/list_types.py +68 -0
- govql_mcp_server-0.1.0/src/govql_mcp_server/tools/passthrough.py +112 -0
- govql_mcp_server-0.1.0/tests/__init__.py +0 -0
- govql_mcp_server-0.1.0/tests/conftest.py +67 -0
- govql_mcp_server-0.1.0/tests/test_describe_type.py +93 -0
- govql_mcp_server-0.1.0/tests/test_graphql_client.py +91 -0
- govql_mcp_server-0.1.0/tests/test_list_types.py +62 -0
- govql_mcp_server-0.1.0/tests/test_no_stdout.py +59 -0
- govql_mcp_server-0.1.0/tests/test_passthrough.py +88 -0
- govql_mcp_server-0.1.0/uv.lock +1809 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
|
|
2
|
+
#/ public-key encryption for .env files /
|
|
3
|
+
#/ [how it works](https://dotenvx.com/encryption) /
|
|
4
|
+
#/----------------------------------------------------------/
|
|
5
|
+
DOTENV_PUBLIC_KEY="02554c3f8b0af44845544039073d017590bcc4495a6a8832f9d50ee8d9cc606fdd"
|
|
6
|
+
|
|
7
|
+
# .env
|
|
8
|
+
UV_PUBLISH_TOKEN="encrypted:BDQbQySFzQ3YqYAmJRx2rDujwXL34EYQ/r8CX4rbvlPrzy/s7NTdnCOl/hNgYmKqTyEunMyWdIiRpeV5vRmNSCyR39lVD+LvAm2pUz1PMjQ6Y7ja31SA89AJCe7fpIvmxxsk4hezjXqB5+thrzS5MiNLzBIZJb7/x+ozzQ8tGfmACY2Sp19mNZaS0S4JCJYNSdv/leS2mP98Uh3bpCpXpqYfCWwrlcS5qBNkG/jXnk9LM40AjlK5RddWVLWwIShIAv32mQX5dMLaymdvM7wIz2RDnvPWKpS6t6g6yuS9ZDpbDvgb26NFW1FFAWQEM4AzAWEGw9bWvAWb2YK7YvQtuE3JuA6sVQS/XcM4Z6tun9wQXWds"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `govql-mcp-server` are documented in this file.
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] — 2026-05-28
|
|
8
|
+
|
|
9
|
+
Initial release.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `execute_graphql` tool — passthrough that runs any GraphQL query against
|
|
14
|
+
the GovQL endpoint and returns the result along with a `last_ingest`
|
|
15
|
+
freshness timestamp.
|
|
16
|
+
- `list_types` tool — returns the names and kinds of every type in the
|
|
17
|
+
GovQL schema, with an optional case-insensitive `kind` filter.
|
|
18
|
+
- `describe_type` tool — returns one GraphQL type's full description
|
|
19
|
+
(fields, arg signatures, input fields, enum values) by name.
|
|
20
|
+
- stdio transport (works with Claude Desktop, Claude Code, Cursor, and any
|
|
21
|
+
other MCP-compatible client that supports stdio servers).
|
|
22
|
+
- Configuration via `GOVQL_ENDPOINT`, `GOVQL_TIMEOUT_MS`, and `LOG_LEVEL`
|
|
23
|
+
environment variables (all optional — defaults point at the public API).
|
|
24
|
+
- Full test suite (23 tests) using FastMCP's in-memory client, including a
|
|
25
|
+
guardrail test that fails if any module writes to stdout.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Contributing to govql-mcp-server
|
|
2
|
+
|
|
3
|
+
This is the Python sub-project of the [GovQL monorepo](https://github.com/govql/govql).
|
|
4
|
+
The rest of the repo (under `us-congress/`) is JavaScript; this package is
|
|
5
|
+
deliberately self-contained.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
You'll need [uv](https://github.com/astral-sh/uv) (the Python package
|
|
10
|
+
manager). Install it with the one-liner from its README, then:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
uv sync # install deps into a local .venv
|
|
14
|
+
uv run pytest # run the test suite
|
|
15
|
+
uv build # build wheel + sdist for publishing
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
uv reads `.python-version` (currently `3.14`) to pick the interpreter; if
|
|
19
|
+
you don't have it installed it will fetch it automatically.
|
|
20
|
+
|
|
21
|
+
## Layout
|
|
22
|
+
|
|
23
|
+
- `src/govql_mcp_server/` — the package
|
|
24
|
+
- `server.py` — FastMCP instance; importing the tools modules registers them
|
|
25
|
+
- `graphql_client.py` — thin httpx wrapper around the GovQL endpoint
|
|
26
|
+
- `tools/` — one file per tool
|
|
27
|
+
- `logger.py` — stderr-only logging (stdout is the MCP transport — see
|
|
28
|
+
"Hard rule" below)
|
|
29
|
+
- `tests/` — pytest suite using FastMCP's in-memory client
|
|
30
|
+
- `docs/design.md` — why the project exists, what's in / out of scope, roadmap
|
|
31
|
+
|
|
32
|
+
## Hard rule: never write to stdout
|
|
33
|
+
|
|
34
|
+
stdout is the MCP transport. Any stray `print()` corrupts the JSON-RPC
|
|
35
|
+
framing and silently breaks every client. Use the logger
|
|
36
|
+
(`from .logger import logger`). The test suite includes
|
|
37
|
+
`tests/test_no_stdout.py` which fails the build if anything in the package
|
|
38
|
+
writes to stdout.
|
|
39
|
+
|
|
40
|
+
## Adding a new tool
|
|
41
|
+
|
|
42
|
+
Each tool gets its own file in `src/govql_mcp_server/tools/` and its own
|
|
43
|
+
test file in `tests/`. Pattern:
|
|
44
|
+
|
|
45
|
+
1. Create `tools/your_tool.py`. Import `mcp` from `..server` and decorate
|
|
46
|
+
an async function with `@mcp.tool`.
|
|
47
|
+
2. Add the module to the import line at the bottom of `server.py` so the
|
|
48
|
+
decorator runs at startup.
|
|
49
|
+
3. Add `tests/test_your_tool.py` using the in-memory `client` fixture from
|
|
50
|
+
`conftest.py`.
|
|
51
|
+
4. Update `README.md`'s tools table and `CHANGELOG.md`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GovQL
|
|
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,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: govql-mcp-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for GovQL — query US Congressional data via GraphQL from any MCP client.
|
|
5
|
+
Project-URL: Homepage, https://govql.us
|
|
6
|
+
Project-URL: Repository, https://github.com/govql/govql
|
|
7
|
+
Project-URL: Issues, https://github.com/govql/govql/issues
|
|
8
|
+
Author: GovQL
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai,congress,government,graphql,mcp,model-context-protocol
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: fastmcp>=3.3.0
|
|
19
|
+
Requires-Dist: httpx>=0.27.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# govql-mcp-server
|
|
23
|
+
|
|
24
|
+
An MCP (Model Context Protocol) server for [GovQL](https://govql.us) — gives
|
|
25
|
+
AI clients like Claude Desktop, Claude Code, and Cursor direct access to the
|
|
26
|
+
US Congressional GraphQL API at [api.govql.us/graphql](https://api.govql.us/graphql)
|
|
27
|
+
without bespoke HTTP wiring.
|
|
28
|
+
|
|
29
|
+
For the design rationale (why FastMCP-Python, the passthrough+curated philosophy,
|
|
30
|
+
roadmap through v0.4), see
|
|
31
|
+
[design.md](https://github.com/govql/govql/blob/main/mcp-server/docs/design.md).
|
|
32
|
+
|
|
33
|
+
## What you can do with it
|
|
34
|
+
|
|
35
|
+
Ask an agent questions like:
|
|
36
|
+
|
|
37
|
+
- *"How did Vermont's two senators vote on the most recent nomination?"*
|
|
38
|
+
- *"Which legislators in the 118th Congress switched parties during their service?"*
|
|
39
|
+
- *"Compare Senator Sanders' voting record to Senator Murkowski's on cloture votes
|
|
40
|
+
in the most recent Congress."*
|
|
41
|
+
|
|
42
|
+
The agent picks the right tool, writes the GraphQL query against the live
|
|
43
|
+
schema, and parses the response — no manual API wrangling.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
The server runs as a per-client subprocess over stdio. Pick your client:
|
|
48
|
+
|
|
49
|
+
### Claude Desktop
|
|
50
|
+
|
|
51
|
+
Edit `claude_desktop_config.json` (Settings → Developer → Edit Config):
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"govql": {
|
|
57
|
+
"command": "uvx",
|
|
58
|
+
"args": ["govql-mcp-server"]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Restart Claude Desktop. The `govql` tools appear in the tools panel.
|
|
65
|
+
|
|
66
|
+
### Claude Code
|
|
67
|
+
|
|
68
|
+
Add to `.mcp.json` in your project (or `~/.mcp.json` for global):
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"govql": {
|
|
74
|
+
"command": "uvx",
|
|
75
|
+
"args": ["govql-mcp-server"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Cursor
|
|
82
|
+
|
|
83
|
+
Settings → MCP → Add Server. Use the same `command` / `args` as above.
|
|
84
|
+
|
|
85
|
+
### Other clients
|
|
86
|
+
|
|
87
|
+
Any MCP-compatible client that supports stdio servers will work. The command
|
|
88
|
+
is `uvx govql-mcp-server` with no required arguments.
|
|
89
|
+
|
|
90
|
+
## Tools
|
|
91
|
+
|
|
92
|
+
| Tool | Purpose |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `execute_graphql` | Run any GraphQL query against the GovQL endpoint. Returns the result plus an `last_ingest` timestamp so the agent can reason about data freshness. |
|
|
95
|
+
| `list_types` | Returns the names and kinds of every type in the GovQL schema. Optional `kind` filter (`"OBJECT"`, `"INPUT_OBJECT"`, `"ENUM"`, etc.) to narrow further. Start here when you don't know what's queryable. |
|
|
96
|
+
| `describe_type` | Returns one type's full details — fields, arg signatures, input fields, enum values. Call after `list_types` to learn the shape of a specific type before writing a query. |
|
|
97
|
+
|
|
98
|
+
## Configuration
|
|
99
|
+
|
|
100
|
+
All env vars are optional — the package is zero-config for end users.
|
|
101
|
+
|
|
102
|
+
| Env var | Default | Purpose |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `GOVQL_ENDPOINT` | `https://api.govql.us/graphql` | Endpoint to query. Override to point at a local dev stack. |
|
|
105
|
+
| `GOVQL_TIMEOUT_MS` | `30000` | Per-request HTTP timeout. |
|
|
106
|
+
| `LOG_LEVEL` | `INFO` | Logging level. Logs go to stderr only (stdout is reserved for the MCP transport). |
|
|
107
|
+
|
|
108
|
+
## Limits (enforced by the upstream API)
|
|
109
|
+
|
|
110
|
+
- Max query depth: 10
|
|
111
|
+
- Max query complexity: ~10 billion points (`first: N` multiplies child cost
|
|
112
|
+
by N — keep page sizes reasonable on deeply nested queries)
|
|
113
|
+
- Rate limit: 100 requests / 60 s per source IP
|
|
114
|
+
|
|
115
|
+
A depth or complexity violation surfaces as a GraphQL `errors` entry in the
|
|
116
|
+
tool response so the agent can adjust and retry.
|
|
117
|
+
|
|
118
|
+
## Data freshness
|
|
119
|
+
|
|
120
|
+
Every `execute_graphql` response includes a `last_ingest` ISO timestamp.
|
|
121
|
+
Vote data refreshes hourly; legislator data refreshes daily.
|
|
122
|
+
|
|
123
|
+
## Status
|
|
124
|
+
|
|
125
|
+
Version 0.1.0 ships three foundational tools: a GraphQL passthrough
|
|
126
|
+
(`execute_graphql`) and two narrow schema-discovery tools (`list_types`,
|
|
127
|
+
`describe_type`). Curated higher-level tools (`find_legislator`,
|
|
128
|
+
`get_voting_record`, `compare_voters`, etc.) are planned for subsequent
|
|
129
|
+
releases — see
|
|
130
|
+
[design.md](https://github.com/govql/govql/blob/main/mcp-server/docs/design.md)
|
|
131
|
+
for the roadmap.
|
|
132
|
+
|
|
133
|
+
## Links
|
|
134
|
+
|
|
135
|
+
- [GovQL project site](https://govql.us)
|
|
136
|
+
- [GraphQL API](https://api.govql.us/graphql)
|
|
137
|
+
- [Source / issues](https://github.com/govql/govql)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# govql-mcp-server
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server for [GovQL](https://govql.us) — gives
|
|
4
|
+
AI clients like Claude Desktop, Claude Code, and Cursor direct access to the
|
|
5
|
+
US Congressional GraphQL API at [api.govql.us/graphql](https://api.govql.us/graphql)
|
|
6
|
+
without bespoke HTTP wiring.
|
|
7
|
+
|
|
8
|
+
For the design rationale (why FastMCP-Python, the passthrough+curated philosophy,
|
|
9
|
+
roadmap through v0.4), see
|
|
10
|
+
[design.md](https://github.com/govql/govql/blob/main/mcp-server/docs/design.md).
|
|
11
|
+
|
|
12
|
+
## What you can do with it
|
|
13
|
+
|
|
14
|
+
Ask an agent questions like:
|
|
15
|
+
|
|
16
|
+
- *"How did Vermont's two senators vote on the most recent nomination?"*
|
|
17
|
+
- *"Which legislators in the 118th Congress switched parties during their service?"*
|
|
18
|
+
- *"Compare Senator Sanders' voting record to Senator Murkowski's on cloture votes
|
|
19
|
+
in the most recent Congress."*
|
|
20
|
+
|
|
21
|
+
The agent picks the right tool, writes the GraphQL query against the live
|
|
22
|
+
schema, and parses the response — no manual API wrangling.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
The server runs as a per-client subprocess over stdio. Pick your client:
|
|
27
|
+
|
|
28
|
+
### Claude Desktop
|
|
29
|
+
|
|
30
|
+
Edit `claude_desktop_config.json` (Settings → Developer → Edit Config):
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"govql": {
|
|
36
|
+
"command": "uvx",
|
|
37
|
+
"args": ["govql-mcp-server"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Restart Claude Desktop. The `govql` tools appear in the tools panel.
|
|
44
|
+
|
|
45
|
+
### Claude Code
|
|
46
|
+
|
|
47
|
+
Add to `.mcp.json` in your project (or `~/.mcp.json` for global):
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"govql": {
|
|
53
|
+
"command": "uvx",
|
|
54
|
+
"args": ["govql-mcp-server"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Cursor
|
|
61
|
+
|
|
62
|
+
Settings → MCP → Add Server. Use the same `command` / `args` as above.
|
|
63
|
+
|
|
64
|
+
### Other clients
|
|
65
|
+
|
|
66
|
+
Any MCP-compatible client that supports stdio servers will work. The command
|
|
67
|
+
is `uvx govql-mcp-server` with no required arguments.
|
|
68
|
+
|
|
69
|
+
## Tools
|
|
70
|
+
|
|
71
|
+
| Tool | Purpose |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `execute_graphql` | Run any GraphQL query against the GovQL endpoint. Returns the result plus an `last_ingest` timestamp so the agent can reason about data freshness. |
|
|
74
|
+
| `list_types` | Returns the names and kinds of every type in the GovQL schema. Optional `kind` filter (`"OBJECT"`, `"INPUT_OBJECT"`, `"ENUM"`, etc.) to narrow further. Start here when you don't know what's queryable. |
|
|
75
|
+
| `describe_type` | Returns one type's full details — fields, arg signatures, input fields, enum values. Call after `list_types` to learn the shape of a specific type before writing a query. |
|
|
76
|
+
|
|
77
|
+
## Configuration
|
|
78
|
+
|
|
79
|
+
All env vars are optional — the package is zero-config for end users.
|
|
80
|
+
|
|
81
|
+
| Env var | Default | Purpose |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `GOVQL_ENDPOINT` | `https://api.govql.us/graphql` | Endpoint to query. Override to point at a local dev stack. |
|
|
84
|
+
| `GOVQL_TIMEOUT_MS` | `30000` | Per-request HTTP timeout. |
|
|
85
|
+
| `LOG_LEVEL` | `INFO` | Logging level. Logs go to stderr only (stdout is reserved for the MCP transport). |
|
|
86
|
+
|
|
87
|
+
## Limits (enforced by the upstream API)
|
|
88
|
+
|
|
89
|
+
- Max query depth: 10
|
|
90
|
+
- Max query complexity: ~10 billion points (`first: N` multiplies child cost
|
|
91
|
+
by N — keep page sizes reasonable on deeply nested queries)
|
|
92
|
+
- Rate limit: 100 requests / 60 s per source IP
|
|
93
|
+
|
|
94
|
+
A depth or complexity violation surfaces as a GraphQL `errors` entry in the
|
|
95
|
+
tool response so the agent can adjust and retry.
|
|
96
|
+
|
|
97
|
+
## Data freshness
|
|
98
|
+
|
|
99
|
+
Every `execute_graphql` response includes a `last_ingest` ISO timestamp.
|
|
100
|
+
Vote data refreshes hourly; legislator data refreshes daily.
|
|
101
|
+
|
|
102
|
+
## Status
|
|
103
|
+
|
|
104
|
+
Version 0.1.0 ships three foundational tools: a GraphQL passthrough
|
|
105
|
+
(`execute_graphql`) and two narrow schema-discovery tools (`list_types`,
|
|
106
|
+
`describe_type`). Curated higher-level tools (`find_legislator`,
|
|
107
|
+
`get_voting_record`, `compare_voters`, etc.) are planned for subsequent
|
|
108
|
+
releases — see
|
|
109
|
+
[design.md](https://github.com/govql/govql/blob/main/mcp-server/docs/design.md)
|
|
110
|
+
for the roadmap.
|
|
111
|
+
|
|
112
|
+
## Links
|
|
113
|
+
|
|
114
|
+
- [GovQL project site](https://govql.us)
|
|
115
|
+
- [GraphQL API](https://api.govql.us/graphql)
|
|
116
|
+
- [Source / issues](https://github.com/govql/govql)
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Releasing govql-mcp-server
|
|
2
|
+
|
|
3
|
+
The steps to ship a new version. Written for v0.1.0 but reusable for subsequent
|
|
4
|
+
releases — just substitute the version number throughout.
|
|
5
|
+
|
|
6
|
+
All commands assume you're in `mcp-server/` unless noted otherwise.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 0. Prerequisites (one-time setup)
|
|
11
|
+
|
|
12
|
+
Skip this section if you've published before.
|
|
13
|
+
|
|
14
|
+
### PyPI account + token
|
|
15
|
+
|
|
16
|
+
1. Create an account at [pypi.org](https://pypi.org/account/register/) (and
|
|
17
|
+
verify your email).
|
|
18
|
+
2. Enable 2FA — PyPI requires it for publishers.
|
|
19
|
+
3. Create a **scoped API token**:
|
|
20
|
+
[pypi.org/manage/account/token/](https://pypi.org/manage/account/token/).
|
|
21
|
+
First release: scope to "Entire account" (the package doesn't exist yet so
|
|
22
|
+
you can't scope to it). After v0.1.0 is up, **revoke that token and create
|
|
23
|
+
a new one scoped to the `govql-mcp-server` project only.**
|
|
24
|
+
4. Store the token somewhere you'll find it again. For local releases, the
|
|
25
|
+
easiest path is to export it before publishing:
|
|
26
|
+
```bash
|
|
27
|
+
export UV_PUBLISH_TOKEN="pypi-AgEI..."
|
|
28
|
+
```
|
|
29
|
+
If you'd rather not type this every time, drop it in your shell's
|
|
30
|
+
per-project environment (e.g. `.env` with dotenvx, or direnv).
|
|
31
|
+
|
|
32
|
+
### MCP registry (mcp.so) account
|
|
33
|
+
|
|
34
|
+
You'll need a free account at [mcp.so](https://mcp.so) to submit the listing
|
|
35
|
+
in step 4. Sign up now if you haven't.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 1. Pre-flight checks
|
|
40
|
+
|
|
41
|
+
Run from `mcp-server/`. All of these should pass before you go further.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Tests green
|
|
45
|
+
uv run pytest
|
|
46
|
+
|
|
47
|
+
# Build artifacts clean (no stale files from a previous build)
|
|
48
|
+
rm -rf dist/
|
|
49
|
+
uv build
|
|
50
|
+
|
|
51
|
+
# Wheel contents look right — should only contain govql_mcp_server/ and a dist-info
|
|
52
|
+
unzip -l dist/govql_mcp_server-0.1.0-py3-none-any.whl
|
|
53
|
+
|
|
54
|
+
# Sdist contents look right — full source tree including tests/, docs/, CHANGELOG
|
|
55
|
+
tar tzf dist/govql_mcp_server-0.1.0.tar.gz
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Quick checklist of things to eyeball:
|
|
59
|
+
|
|
60
|
+
- `CHANGELOG.md` has an entry for the version you're about to release
|
|
61
|
+
- `pyproject.toml`'s `version` matches that CHANGELOG entry
|
|
62
|
+
- `README.md` describes the *current* tool set (no "coming soon" wording)
|
|
63
|
+
- No half-finished branches or commented-out code on the release commit
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 2. Real MCP client test (gate before publishing)
|
|
68
|
+
|
|
69
|
+
This is the only test that proves "an actual agent can use this." Don't
|
|
70
|
+
publish without it.
|
|
71
|
+
|
|
72
|
+
Pick a client. **Claude Desktop** is recommended for the first release because
|
|
73
|
+
it makes the tool calls visible in the UI.
|
|
74
|
+
|
|
75
|
+
### Wire up the *local* build (not the PyPI version)
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Confirm the local entry point works
|
|
79
|
+
GOVQL_ENDPOINT=https://api.govql.us/graphql uv run govql-mcp-server
|
|
80
|
+
# (Ctrl-C to stop — you're just confirming it starts cleanly. No prompt means it's
|
|
81
|
+
# waiting on stdin for MCP messages, which is correct.)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
In Claude Desktop, edit `claude_desktop_config.json` (Settings → Developer →
|
|
85
|
+
Edit Config) and add an entry pointing at this checkout:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"mcpServers": {
|
|
90
|
+
"govql-local": {
|
|
91
|
+
"command": "uv",
|
|
92
|
+
"args": [
|
|
93
|
+
"--directory",
|
|
94
|
+
"/home/astout5/govql/mcp-server",
|
|
95
|
+
"run",
|
|
96
|
+
"govql-mcp-server"
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Restart Claude Desktop. Confirm `govql-local` shows up in the tools panel
|
|
104
|
+
with `execute_graphql`, `list_types`, and `describe_type` listed.
|
|
105
|
+
|
|
106
|
+
### The test prompt
|
|
107
|
+
|
|
108
|
+
Ask:
|
|
109
|
+
|
|
110
|
+
> *How did Vermont's two senators vote on the most recent nomination?*
|
|
111
|
+
|
|
112
|
+
Expected behavior:
|
|
113
|
+
|
|
114
|
+
1. The agent calls `list_types` / `describe_type` as needed (or already
|
|
115
|
+
knows the schema from a prior session).
|
|
116
|
+
2. It writes a query against `allVotes` + `votePositions` filtering for
|
|
117
|
+
Vermont senators and the latest nomination.
|
|
118
|
+
3. It returns a concise answer naming both senators and their positions.
|
|
119
|
+
|
|
120
|
+
If anything is off (the agent gets confused, the query fails, the answer is
|
|
121
|
+
wrong), fix it before publishing — the issue is almost certainly in the
|
|
122
|
+
`execute_graphql` docstring in
|
|
123
|
+
`src/govql_mcp_server/tools/passthrough.py`, which is the agent's primary
|
|
124
|
+
guide.
|
|
125
|
+
|
|
126
|
+
### Capture the transcript
|
|
127
|
+
|
|
128
|
+
Once it works, copy the transcript into `README.md` under a "Try it" or
|
|
129
|
+
"Example" section so PyPI visitors see a concrete demo on the project page.
|
|
130
|
+
Commit the README change before publishing.
|
|
131
|
+
|
|
132
|
+
### Remove the local config
|
|
133
|
+
|
|
134
|
+
After the test, remove the `govql-local` entry from
|
|
135
|
+
`claude_desktop_config.json` so you don't have two GovQL servers competing
|
|
136
|
+
once the real one is installed.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 3. Publish to PyPI
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# 1. Re-build with the final README/CHANGELOG/version in place.
|
|
144
|
+
rm -rf dist/
|
|
145
|
+
uv build
|
|
146
|
+
|
|
147
|
+
# 2. Publish. UV_PUBLISH_TOKEN must be set (see Prerequisites).
|
|
148
|
+
uv publish
|
|
149
|
+
|
|
150
|
+
# 3. Verify it's live by installing it in a throwaway location.
|
|
151
|
+
# Should print version 0.1.0 and exit cleanly (subprocess waits on stdin
|
|
152
|
+
# for MCP messages; just confirm it starts).
|
|
153
|
+
uvx --refresh govql-mcp-server --help 2>&1 | head -5
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
If the publish fails on `name already exists`: someone took the name. Pick
|
|
157
|
+
one of the fallbacks from the original plan (`govql`, `mcp-govql`,
|
|
158
|
+
`govql-mcp`), update `pyproject.toml` + every README install snippet to match,
|
|
159
|
+
re-run pre-flight, and try again.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 4. Tag the release in git
|
|
164
|
+
|
|
165
|
+
From the **repo root** (not `mcp-server/`):
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
cd /home/astout5/govql
|
|
169
|
+
|
|
170
|
+
# Sanity: the working tree should be clean and on the merge commit that includes the release.
|
|
171
|
+
git status
|
|
172
|
+
git log -1 --oneline
|
|
173
|
+
|
|
174
|
+
# Tag and push.
|
|
175
|
+
git tag -a govql-mcp-server-v0.1.0 -m "govql-mcp-server v0.1.0"
|
|
176
|
+
git push origin govql-mcp-server-v0.1.0
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The tag is namespaced with `govql-mcp-server-` so it doesn't collide with
|
|
180
|
+
future tags for other sub-projects (e.g. a hypothetical
|
|
181
|
+
`us-congress-api-v1.0.0`).
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 5. Submit to the MCP registry (mcp.so)
|
|
186
|
+
|
|
187
|
+
1. Log into [mcp.so](https://mcp.so).
|
|
188
|
+
2. Click "Submit MCP Server" (or whatever the current entry point is called).
|
|
189
|
+
3. Fill in:
|
|
190
|
+
- **Name:** `govql`
|
|
191
|
+
- **Description:** "MCP server for GovQL — query US Congressional voting
|
|
192
|
+
data (legislators, roll-call votes, etc.) via GraphQL from any MCP
|
|
193
|
+
client."
|
|
194
|
+
- **GitHub URL:** `https://github.com/govql/govql/tree/main/mcp-server`
|
|
195
|
+
- **Install / config snippet** (JSON):
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"mcpServers": {
|
|
199
|
+
"govql": {
|
|
200
|
+
"command": "uvx",
|
|
201
|
+
"args": ["govql-mcp-server"]
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
4. Submit and wait for moderation (typically a few hours to a few days).
|
|
207
|
+
5. Once approved, copy the registry URL into the next CHANGELOG entry under
|
|
208
|
+
the relevant version so future contributors can find it.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 6. Post-release sanity checks
|
|
213
|
+
|
|
214
|
+
About 5 minutes after `uv publish`:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Confirm the package is visible on PyPI.
|
|
218
|
+
curl -sS https://pypi.org/pypi/govql-mcp-server/json | jq '.info.version, .info.home_page'
|
|
219
|
+
|
|
220
|
+
# Confirm a fresh install from PyPI works (use --refresh to bypass uv's cache).
|
|
221
|
+
uvx --refresh --from govql-mcp-server==0.1.0 govql-mcp-server --help 2>&1 | head -5
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Then in Claude Desktop, replace the local-build config with the PyPI version
|
|
225
|
+
(the snippet in `README.md`) and re-run the Vermont prompt to confirm the
|
|
226
|
+
published artifact behaves identically to the local build.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 7. Graceful-exit check
|
|
231
|
+
|
|
232
|
+
Before stopping work, confirm every item below — this is the discipline that
|
|
233
|
+
makes a paused-mid-project portfolio piece still look intentional:
|
|
234
|
+
|
|
235
|
+
- [ ] Latest version is on PyPI
|
|
236
|
+
- [ ] Matching git tag is pushed
|
|
237
|
+
- [ ] `CHANGELOG.md` has the entry
|
|
238
|
+
- [ ] `README.md` accurately describes the *current* tool set
|
|
239
|
+
- [ ] No half-merged branches, no commented-out scaffolding, no TODO
|
|
240
|
+
comments pointing at the next version
|
|
241
|
+
- [ ] MCP-server Docusaurus page reflects the current tool set
|
|
242
|
+
- [ ] MCP registry listing submitted (or approved)
|