MCP server for the GameFunds funding directory + outreach pipeline. Provides access to 225+ game funding sources (publishers, VCs, grants, project investors) with full-text search, filtering, project matching, pitch review, and submission tracking.
GameFunds demonstrates strong domain-specific design with 13 well-named tools following verb_noun conventions (search_funding, filter_funding, match_project, etc.). All tools have substantive descriptions (100-400+ chars) explaining WHAT, WHEN, and WHY. Input schemas are present with types and descriptions for all parameters. However, output schemas are documented only in descriptions, not as formal JSON Schema objects returned by the tools. Error handling is minimal, no recovery guidance, no categorization of retryable vs fatal errors. Tool composition is excellent (search → filter → get_entity → set_status pipeline), but some tools like review_pitch accept markdown as a string without validation guidance. Parameter constraints are well-documented in descriptions but not enforced via enums where applicable (e.g., stage, status, funding_type should be enums). Security is adequate (no secrets in params, write operations gated), but no explicit permission declarations or audit trail guidance.
Append a dated note to a pipeline entry without changing status. Use after a call, email, or meeting when status stays the same — use `set_status` to change status. Notes are appended with a date, never overwritten. Returns: `{slug, note_count}`.
Cheap check whether the upstream repo changed (commit SHA only, no download). Returns: `{has_update, current_sha, last_synced_sha, last_synced_at, commit_message, commit_date}`.
Filter by structured fields. All arguments are optional. `section`: A-G (call `gamefunds_help("sections")` if you need section meanings). `budget_tier`: 1=$ (<200k), 2=$%$ (200k-2M), 3=$%$$ (>2M). `min_comm`: 1-3, how responsive they are to email. `has_email`: email contact only, no web forms. Returns: `{total_matched, results: [EntityBrief], filters_applied}`. If `total_matched` > 30, narrow filters instead of paging.
Help text on concepts, sections, funding types, and guides. `topic`: sections | funding_types | guides | all. Returns markdown.
Full record: all links, full notes, contact, submission path, reputation warnings, `terms_raw` (raw financial terms text from the catalog), plus your pipeline state for this entity if it exists. Call for 2-3 finalists only, not the whole candidate list. Returns: full `Entity` + `pipeline: PipelineState | null`.
Output schemas documented only in descriptions, not as formal JSON Schema. Tools return complex nested objects (e.g., match_project returns {by_type: {publisher|grant|vc_equity|project_investor: [...]}, hard_filtered, below_cutoff, ...}) but LLMs cannot parse these without explicit schema definitions.
Enum constraints documented in descriptions but not enforced in schema. Parameters like 'status' (not_contacted|contacted|in_talks|rejected|signed|passed), 'stage' (concept|prototype|vertical_slice|alpha|beta), and 'funding_type' (publisher|vc_equity|grant|project_investor) should be JSON Schema enums, not free-form strings.
No error handling guidance. Tools like review_pitch (accepts markdown) and sync_directory (network I/O) lack recovery hints. If review_pitch receives invalid markdown or sync_directory times out, LLM has no guidance on retry strategy or fallback.
Inferred effective spec: 2026-07-28+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
Canonical pitch deck structure from PitchDeckTutorial.md: slides, what each must contain, weights. If you pass `target_slug`, the rubric adds that entity's criteria. `funding_type`: publisher | vc_equity | grant | project_investor — DIFFERENT rubrics; grants want different content than VCs. This is a working rubric, not text to paste. You write the deck. Returns: `{funding_type, slides: [{n, title, must_contain: [str], weight, common_mistakes: [str]}], target_specific: [str]}`.
Everything about HOW to submit to a specific entity: channel (email vs web form), address/link, `submit_links` (parsed submission URLs), stated criteria extracted from notes ("Only $2M+ games", "No sandbox games"), budget tier, responsiveness, warnings, portfolio titles (for tone matching). Call BEFORE writing a pitch or email. Returns: `{slug, name, channel, target, stated_criteria: [str], hard_filters: [str], warnings: [str], portfolio: [str], comm_rating, terms_raw, submit_links}`.
Your submission tracker. `stale_days=30` -> contacted/in_talks entries idle >30 days or with an overdue follow-up. Call at the start of a fundraising session. Returns: `{by_status: {status: count}, entries: [{slug, name, status, last_contact, next_followup, days_stale, last_note}]}`.
Match a project to funding sources. Deterministic scoring, NOT an LLM. `stage`: concept | prototype | vertical_slice | alpha | beta. `limit_per_type`: candidates per group (default 3, max 10). Returns candidates grouped by funding path — you rank and recommend from `reasons` and `confidence`; do not treat `score` as an oracle. Returns: `{by_type: {publisher|grant|vc_equity|project_investor: [{...EntityBrief, score, confidence, breakdown, reasons}]}, hard_filtered, below_cutoff, genre_signal, genre_terms, genre_warning?, budget_signal, budget_warning?, note}`. `budget_usd` must be positive. The catalog has meaningful budget resolution around ~$5k-$5M (from amount_min/max data). Outside that scale, `budget_signal` is `above_range` or `below_range` (warning + all candidates confidence=low). `budget_signal`: in_range | above_range | below_range. `genre_signal`: good (>=1 genre term hit the catalog) | none (zero hits -> warning, all confidence=low). `genre_terms`: {matched, unmatched} — unmatched terms are informational, not a penalty. `confidence`: low | medium | high per candidate. `breakdown`: points (genre, budget, country, stage, comm). Grants (section G) are hard-filtered by country — a grant from another country usually does not apply.
Hard, deterministic deck check. Does NOT judge quality — that is your job. Checks: missing required slides, missing concrete numbers (budget, ask, recoup, timeline, team size), missing build/vertical-slice link, deck length, target hard-filter violations (e.g. sandbox game to Team17). `include_rubric`: if True, attaches the full rubric (`rubric`) — use when you need slide structure in the same call as the review. Returns: `{hard_findings: [{severity, slide, issue}], coverage: {slide_name: present|missing|thin}, deck_stats: {slides, words}, rubric?}`. After the result: do qualitative assessment yourself from `rubric` and `coverage`. Input format: markdown/text. The server does not parse PDF or PPTX — extract text first.
Full-text search across 225+ game funding sources (name, country, game titles, notes). Use when you know a name or want a keyword ("roguelike", "Sweden", "Devolver", "turn-based", "free-to-play", "AAA/AA"). Hyphens, slashes, and parentheses are safe. Do NOT use this to match a project to funders — use `match_project` for that. Returns: `{total_matched: int, results: [EntityBrief]}`. Briefs omit full notes and links — call `get_entity(slug)` for those.
`status`: not_contacted | contacted | in_talks | rejected | signed | passed (`passed` = you dropped out, `rejected` = they declined). Notes are APPENDED with a date, never overwritten. Returns: `PipelineState`.
Fetch and parse the catalog from GitHub. Your pipeline data is NOT touched. Default `dry_run=True` — shows what would change. Writing requires explicit `dry_run=False`. `full_diff=False` returns counts + first 10 changes (diff can be large).
review_pitch accepts 'deck_markdown' as free-form string with no validation guidance. Description says 'extract text first' but does not specify format, encoding, or length limits. LLMs may pass binary data or extremely long strings.
No permission declarations. Tools like set_status and sync_directory modify state but do not declare required scopes (e.g., 'write:pipeline', 'admin:catalog'). Audit trail guidance is absent.