gengomcp
An MCP server (Python, stdio transport) that lets an agent retrieve ACL conference papers about NLP from a Qdrant vector database. It combines semantic search (Sentence‑Transformers embeddings) with structured filtering by bibliographic fields like publication year and venue.
Qdrant access is currently limited. This server queries a shared Qdrant collection of ACL NLP papers. If you'd like credentials to use it, please reach out to the project maintainer — access may be granted at a limited scale. You'll receive a
QDRANT_URL,QDRANT_KEY, andQDRANT_COLLECTION_NAMEto add to your.envor MCP clientenvfield.
Quick start
# 1. install (from the project root)
uv sync # creates .venv and installs deps (mcp, qdrant-client, sentence-transformers, python-dotenv)
# 2. configure — NEVER commit real keys
cp .env.example .env # edit .env with your Qdrant credentials
# 3. run
uv run gengomcp # console script (registered by pyproject.toml)
# or: uv run python server.py
# or: uv run python main.py
The server reads its .env from the project root (next to server.py), so it also
works when launched from another working directory (e.g. by an MCP client or a
sandbox) — see Wiring it into an MCP client.
The API key is read from the environment and is never logged or hard-coded. For local runs, copy
.env.example→.envand fill in your Qdrant connection details (.envis gitignored). For MCP-client deployment, you can inject the same variables via your client'senvfield instead — see Configuring credentials via the MCP client.
Wiring it into an MCP client
Any MCP client over stdio works. The command below is cwd‑independent (the
absolute server path means the server loads .env from its own project root),
so it's safe to launch from any working directory.
Example for Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"gengomcp": {
"command": "uv",
"args": ["run", "--project", "/Users/.../gengomcp", "gengomcp"]
}
}
}
Using the installed gengomcp console script (registered by pyproject.toml) is
the simplest entry point. For setups without uv, point command at the script
in the venv directly:
"command": "/Users/.../gengomcp/.venv/bin/gengomcp",
"args": []
Configuring credentials via the MCP client
Credentials (QDRANT_URL, QDRANT_KEY, QDRANT_COLLECTION_NAME) are read from
the process environment, so you can inject them directly through your MCP
client's env field — no .env file required. This is the recommended way to
wire per-agent secrets:
{
"mcpServers": {
"gengomcp": {
"command": "uv",
"args": ["run", "--project", "/Users/.../gengomcp", "gengomcp"],
"env": {
"QDRANT_URL": "https://<cluster>.cloud.qdrant.io",
"QDRANT_KEY": "<your-api-key>",
"QDRANT_COLLECTION_NAME": "papers_test"
}
}
}
}
Precedence: environment variables set by the MCP client (
envfield) always take priority. A local.envfile is only used as a fallback (loaded withpython-dotenv, which does not override existing env vars). This means you can use.envwhile developing locally and switch to the clientenvfield for production without changing the server.
Required variables (no defaults):
| Variable | Description |
|---|---|
QDRANT_URL |
Qdrant cluster URL |
QDRANT_KEY |
Qdrant API key |
QDRANT_COLLECTION_NAME |
Collection to search (e.g. papers_test) |
Optional variables (have defaults, see .env.example):
EMBEDDING_MODEL, AUTO_CREATE_INDEXES, LOG_LEVEL.
If a required variable is missing at startup, the server exits with a clear error explaining how to set it.
Poolside (pool)
The server is already registered for you. Verify with:
pool mcp list # shows: gengomcp
pool mcp get gengomcp # shows the stored command + args
It was added with the cwd‑independent command above, stored under mcp_servers
in ~/.config/poolside/settings.yaml (personal config). The server reads its
own .env, so no keys are stored in the poolside config. To remove it later:
pool mcp remove gengomcp
Tools
| Tool | Purpose |
|---|---|
search_papers |
Semantic search for ACL NLP papers. USE when the user has a topic/question. Embeds query and returns the most similar papers, optionally narrowed by structured filters. |
get_paper |
USE to inspect a single ACL NLP paper in full detail (abstract, summaries, entities) when you already have its paper_uuid from a search result. |
list_papers |
USE to browse/filter ACL NLP papers with no query text — pure structured filtering + pagination (e.g. "all ACL 2024 papers"). |
get_collection_info |
USE first to discover available venues, years, fields of study, and vector names before building filters. |
search_papers parameters
query str (required) search text
limit int = 10 (clamped 1..100)
vector_name str = "overview" one of overview/approach/challenge/outcome
year int exact publication year (e.g. 2026)
year_min / year_max int year range (inclusive)
year_gt / year_lt int year range (exclusive)
venue str substring match on the booktitle (e.g. "Annual Meeting")
collection_acronym str exact venue acronym, e.g. "ACL" / "EMNLP" / "NAACL"
collection_id str e.g. "2026.acl"
field_of_study list[str] membership on `field_of_studies` (e.g. ["Reasoning"])
author str name contained in `author_names`
min_score float only return results with similarity >= this value
All filters are AND‑combined, so you can layer them, e.g.
search_papers(query="...", year_min=2020, collection_acronym="ACL").
Example tool calls
search_papers(query="stress testing large language models",
vector_name="overview", year_min=2024, year_max=2026,
collection_acronym="ACL", limit=5)
get_paper(paper_id="000036a6-e2be-523e-8b8d-0f2cbe2b39e7")
list_papers(collection_acronym="EMNLP", year=2024, limit=20)
list_papers(field_of_study=["Reasoning"], author="Pan", limit=20, offset=<prev_uuid>)
How it works
- Secrets & config — credentials are read from environment variables
(
QDRANT_URL,QDRANT_KEY,QDRANT_COLLECTION_NAME). For local runs, copy.env.example→.envand fill them in. For MCP deployment, inject the same variables via your client'senvfield instead.QDRANT_KEYis used directly by the Qdrant client and is never printed or hard-coded. - Payload indexes — Qdrant requires a payload index to filter on a
field. This collection ships with no indexes, so the server creates the needed
ones idempotently at startup (non-destructive — it only adds indexes).
Disable with
AUTO_CREATE_INDEXES=0if you manage indexes yourself. - Embeddings — queries are embedded with Sentence‑Transformers using
Snowflake/snowflake-arctic-embed-s, the only model that matches this collection's 384-dimensional index. The server can truncate+renormalise other model outputs to the index dimensionality (matryoshka‑style) as a safety net, but models in a different embedding space (e.g. the 768-dimm-v1.5) will still fail to retrieve — see The embedding model. - Named vectors — the
overview/approach/challenge/outcomenamed vectors in the collection are all 384-dimensional.
The embedding model
The collection's vectors are 384-dimensional and were built with the
Snowflake arctic-embed "s" model (Snowflake/snowflake-arctic-embed-s).
This is the only model that produces embeddings in the correct space for
this index — it is the default and should not be changed.
The Snowflake family ships in several sizes, but only the s (384-dim) variant
matches this collection's index:
| model | dims | works with this index? |
|---|---|---|
Snowflake/snowflake-arctic-embed-s |
384 | ✅ yes (default) |
snowflake-arctic-embed-m-v1.5 |
768 | ❌ no — different embedding space |
snowflake-arctic-embed-l-v1.5 |
1024 | ❌ no — different embedding space |
The m and l variants live in different embedding spaces than the
stored 384-dim vectors — even though the server can truncate to match
dimensionality, the resulting embeddings will not align with the index and
retrieval will fail (verified: ~0 cosine similarity against stored vectors).
Keep EMBEDDING_MODEL at its default unless you re-index the collection with a
different model.
Project layout
gengomcp/
├── server.py # the MCP server (tools + Qdrant/Embeddings glue)
├── main.py # thin launcher
├── pyproject.toml # deps + `gengomcp` console script
├── uv.lock # pinned dependency versions
├── LICENSE # MIT
├── .env # local secrets (gitignored — never commit)
├── .env.example # template (committed)
└── README.md
Development / testing
uv run python -c "import server; print('ok')"
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gengomcp-1.0.0.tar.gz.
File metadata
- Download URL: gengomcp-1.0.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e756cb96cd5d2866e09bd60270c3cfd7b28e4e799af1c965425177c0f2250f7
|
|
| MD5 |
748eb4c3ce995bf7b5d789103daef189
|
|
| BLAKE2b-256 |
44c8b124474061005b22698dd1d0d7d60bd659ebda6ea636212f3378de487e26
|
File details
Details for the file gengomcp-1.0.0-py3-none-any.whl.
File metadata
- Download URL: gengomcp-1.0.0-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d4d4c8eaf9fc11a7abaf6e936e860fd7a82e391614b51b1c4cb38a63c8b2b20
|
|
| MD5 |
7dd354575991a140806221c1f34f0850
|
|
| BLAKE2b-256 |
77e54e8780b44d93ede220e326d76e97c6f91497ac59a93dca9074e6201e306a
|