Grant Hunter MCP
README.md
# Grant Hunter MCP
Grant Hunter MCP is a FastAPI-based Model Context Protocol (MCP) service for grant discovery and pitch drafting.
## Repository Role
This repository contains the **public MCP server layer** of the Grant Hunter product. It exposes HTTP endpoints that any MCP-compatible client can call to search for grants, generate pitches, and interact with Google Workspace.
The private product layer—user-facing UI, workflow orchestration, and end-user authentication—lives in a separate private repository. This public repo exists so that external developers and MCP clients can integrate with the server independently.
For a visual overview of how the public MCP server relates to the broader product, see the [architecture diagram in TECHNICAL.md](TECHNICAL.md#system-diagram).
## Non-Goals
The following are **not** part of this repository:
- User-facing UI or frontend components
- End-to-end product workflows spanning the private product layer
- User account management, billing, or tenancy logic
- Full OAuth2 token lifecycle service
- Kubernetes/Helm deployment templates
- Any private product business logic not directly tied to MCP endpoints
## Verified Capabilities
- `POST /query_grants`
- Searches Grants.gov by keyword.
- Uses async `httpx` call path with retry/backoff.
- Applies optional `focus_area` filtering over returned opportunities.
- Deduplicates by opportunity number.
- Sorts by close date.
- Falls back to mock grants if upstream lookup fails, with response metadata (`fallback_used`, `data_source`).
- `POST /generate_pitch`
- Generates a draft pitch using Gemini (`gemini-2.0-flash` then `gemini-2.0-flash-lite`).
- Falls back to a deterministic template when generation fails or no API key is set.
- `POST /manage_google_services`
- Creates a Gmail draft and a Calendar event from request inputs.
- Returns a typed response contract (`GoogleServicesOutput`).
- Supports optional server-side OAuth access token refresh when `refresh_token`, `client_id`, and `client_secret` are provided.
- Supports `oauth_session_id` to use persisted server-side OAuth credentials.
- `POST /oauth_sessions`
- Persists OAuth credentials server-side and returns a `session_id`.
- `DELETE /oauth_sessions/{session_id}`
- Deletes a persisted OAuth session.
- Supports `DEMO_MODE=TRUE` to simulate success.
- `GET /health`
- Basic health endpoint.
- Request observability
- Adds `x-request-id` correlation header to every response.
- Emits structured request completion logs and external Grants.gov call timing logs.
## Current Limitations
- Partial async migration:
- Grants lookup is async.
- Google API SDK calls are sync and currently executed via route-level thread offload.
- Contract drift:
- `focus_area` is now applied as a simple substring filter; advanced semantic filtering is not implemented yet.
- OAuth lifecycle:
- Access-token-only mode is still supported.
- Server-side refresh is now supported per request when refresh credentials are provided.
- Persisted session storage is SQLite-backed and intended for backend service use.
- Encryption-at-rest and external secret-manager integration are not implemented yet.
- Date safety:
- Deadline dates are now validated; accepted formats are `%B %d, %Y` or `%Y-%m-%d`.
- Delivery posture:
- Test suite and CI are planned but not yet implemented.
- Docker usage is documented as roadmap; no Dockerfile is currently present in this repository.
## Architecture Docs
- [TECHNICAL.md](TECHNICAL.md): current architecture and component behavior.
- [ARCHITECTURE_REVIEW.md](ARCHITECTURE_REVIEW.md): structured architecture review, risk matrix, and remediation backlog.
- [TODO.md](TODO.md): prioritized roadmap and issue-linked backlog.
## Setup (Local)
### Prerequisites
- Python 3.11+
- Gemini API key for AI pitch generation
### Install
```bash
pip install -r requirements.txt
```
### Configure
```bash
cp .env.example .env
```
Set at least:
- `GEMINI_API_KEY` (required for live AI generation)
Optional:
- `MCP_SERVER_URL`
- `LOG_LEVEL`
- `DEMO_MODE`
### Run
```bash
uvicorn main:app --reload --host 0.0.0.0 --port 8000
```
Docs:
- `http://localhost:8000/docs`
## API Reference
### `GET /health`
Returns service health status.
### `POST /query_grants`
Request:
```json
{
"keyword": "clean energy",
"max_results": 20,
"focus_area": "renewable energy"
}
```
Response includes:
- `fallback_used`: `true` when fallback data is used
- `data_source`: `grants_gov` or `mock_fallback`
- If `focus_area` is provided, results are filtered by matching text in grant title/description/category/agency.
### `POST /generate_pitch`
Request:
```json
{
"startup_name": "CleanTech Solutions",
"focus_area": "Renewable Energy",
"grant_title": "Clean Energy Innovation Grant"
}
```
### `POST /manage_google_services`
Request:
```json
{
"grant_title": "Clean Energy Innovation Grant",
"deadline_date": "December 15, 2025",
"oauth_token": "oauth_access_token",
"refresh_token": "optional_refresh_token",
"client_id": "optional_client_id",
"client_secret": "optional_client_secret",
"token_uri": "https://oauth2.googleapis.com/token"
}
```
Or session-based request:
```json
{
"grant_title": "Clean Energy Innovation Grant",
"deadline_date": "December 15, 2025",
"oauth_session_id": "session_id_from_oauth_sessions"
}
```
## Error Contract
Error responses are standardized with:
```json
{
"code": "MACHINE_READABLE_CODE",
"message": "Human readable message",
"details": { "optional": "context" }
}
```
## Issue Automation
The repository includes automatic TODO issue creation:
- Workflow: `.github/workflows/create-todo-issues.yml`
- Script: `scripts/create_todo_issues.py`
Run manually via GitHub Actions `workflow_dispatch` or on push to `main` when TODO/script changes.
## Security Notes
- Never commit `.env`.
- Avoid logging tokens or generated sensitive content.
- Input validation is enforced through Pydantic models.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contribution guide, including expected PR types, non-goals, and code style notes.
Quick checklist:
1. Review `TODO.md` and `ARCHITECTURE_REVIEW.md`.
2. Keep behavior and docs in sync.
3. Add tests for new behavior whenever possible.
4. Do not commit secrets.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessUnresponsive