Skip to main content
Glama

Marvin MCP

Ask Marvin, Marvin Labs' equity research analyst, from Claude Desktop, Claude Code or any other MCP client. It runs locally over stdio and only calls the Marvin Labs public API (/v1/responses, /v1/conversations, /v1/agent_results) with your own API key. Conversations you start here show up in the Marvin app, and app conversations can be continued from here.

Setup

You need:

  1. Access. This is a private alpha version. Please email marvin@marvin-labs.com for access.

  2. An API key. In the app: Account → API keys → Add new key.

  3. uv (curl -LsSf https://astral.sh/uv/install.sh | sh).

Then, from the project you want Marvin in, run:

uvx --from git+https://github.com/Marvin-Labs/marvin-mcp marvin-mcp setup

It asks for your API key, checks that it works, and adds Marvin to the clients it finds. By default that is this project only:

Client

setup (this project)

setup --global (all projects)

Claude Code

yes, private to you (not in .mcp.json)

yes

Codex, CLI and app

yes, in .codex/config.toml, kept out of git; Codex loads it once you trust the project

yes

Claude Desktop

no per-project setting

yes

ChatGPT desktop

no per-project setting

prints the values to paste into its settings

Run it again to change the key. --yes sets up every client found without asking; MARVIN_API_KEY in the environment skips the key prompt; --api-url points the clients at another environment, such as stg.

By hand

Any MCP client that starts local (stdio) servers works. The command is uvx, the arguments are --refresh --from git+https://github.com/Marvin-Labs/marvin-mcp marvin-mcp, and MARVIN_API_KEY goes in the server's environment. For example:

claude mcp add marvin --env MARVIN_API_KEY=ak_... \
  -- uvx --refresh --from "git+https://github.com/Marvin-Labs/marvin-mcp" marvin-mcp
codex mcp add marvin --env MARVIN_API_KEY=ak_... \
  -- uvx --refresh --from "git+https://github.com/Marvin-Labs/marvin-mcp" marvin-mcp

Claude Desktop on macOS does not see your shell's PATH, so give it the full path to uvx (which uvx).

--refresh fetches the latest version each time your client starts the server. To stay on one version instead, drop it and pin a commit: git+https://github.com/Marvin-Labs/marvin-mcp@<sha>.

Related MCP server: octagon-mcp-server

Tools

Tool

Does

ask_marvin(question, conversation_id?)

Asks a question, in a new conversation or continuing one. Returns the answer, or a response_id if it is still working

get_response(response_id)

Waits a little longer for an answer that is still running

cancel_response(response_id)

Stops a running answer

list_conversations(limit?, cursor?)

Your conversations, most recent first, including the app's

get_conversation(conversation_id, limit?, cursor?)

A conversation's questions and answers

list_agent_results(company?, agent?, mine?, limit?, cursor?)

Reports Marvin's research agents have written that you can read: yours, shared with you, and public ones

get_agent_result(agent_result_id)

One report, in full

get_format_guide()

How to show the table and chart blocks in answers

Answers often take a few minutes. MCP clients give up on a tool call long before that, so ask_marvin starts the answer in the background and waits for at most MARVIN_WAIT_SECONDS (default 50). If the answer isn't ready by then, the model calls get_response until it is.

Answers can contain tables and charts, written as JSON in ```financial-table and ```echarts blocks that the Marvin app renders. get_format_guide explains how to turn the blocks into markdown tables, or into charts if the client can draw them.

Configuration

Variable

Default

MARVIN_API_KEY

(required)

Your Marvin API key

MARVIN_API_URL

https://app-api.marvin-labs.com

Another environment, e.g. stg or a local API (http://localhost:<port>)

MARVIN_WAIT_SECONDS

50

How long one tool call waits for an answer

Every answer is a normal Marvin chat turn and uses your credits the same way.

Development

uv run pytest
MARVIN_API_KEY=ak_... MARVIN_API_URL=http://localhost:<port> uv run marvin-mcp   # stdio

To try a change in real clients before it is published, run setup from your checkout and pass --source, so the clients also start the server from it (add --api-url for stg or a local API):

uvx --from <checkout> marvin-mcp setup --source <checkout>

uv rebuilds the checkout whenever a file under src/ changes ([tool.uv] cache-keys in pyproject.toml), so the next run and the next client restart pick up your edits. Run setup again without --source to switch back to the published version.

This repository is published automatically from Marvin Labs' main codebase, where the client is maintained, and is replaced on every release. Changes made here are overwritten, so it does not take pull requests.

Licence

MIT, see LICENSE.

Available Tools

5 tools
ask_marvinA

Ask Marvin a question; returns its answer, or a response_id to poll.

NameRequiredDescriptionDefault
questionYesThe question, in plain language.
conversation_idNoContinue this conversation (the conversation_id of an earlier answer, or one from list_conversations). Omit to start a new one.

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose the single most surprising behavior: the call may return a response_id instead of an answer, meaning results can be deferred. It does not explain what triggers the async path, expected latency, or that a paused request may need cancelling, which leaves meaningful gaps for an un-annotated tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single clause with zero filler, front-loading the action and then the two possible outcomes. Nothing could be removed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with a full output schema and documented parameters, the description covers what it does and the one non-obvious outcome. The only missing piece, naming the polling sibling, belongs to usage guidance rather than making the definition incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%; conversation_id already documents how to continue a thread. The description adds no syntax, format, or constraint detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Ask Marvin a question") and adds the distinctive dual return mode. It does not name or distinguish itself from siblings like get_response or list_conversations, so the agent must infer the relationship, but the core purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase "or a response_id to poll" implies a follow-up step exists but never names get_response as the tool to poll with, nor mentions cancel_response. Usage is implied rather than instructed, leaving the agent to guess the async workflow from sibling names alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_responseB

Stop an answer that is still running.

NameRequiredDescriptionDefault
response_idYesThe response_id ask_marvin returned.

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are supplied, so the description carries the full behavioral burden. It doesn't say whether cancellation is idempotent, whether the response_id becomes invalid afterward, whether partial output is retained, what error surfaces for an unknown or completed id, or what permissions are needed — all material for a mutation tool with zero annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short, front-loaded sentence with no filler, and the key constraint (still running) is placed where it will be read. It is efficient rather than padded, though the brevity borders on under-specification.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values needn't be explained, but for a state-changing cancel operation with no annotations the description should cover post-cancellation state and failure modes. As written, an agent knows what the tool intends but not what to expect from it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single parameter is already documented as the response_id returned by ask_marvin. The description adds no extra meaning about the identifier beyond what the schema states, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Stop") applied to a specific resource ("an answer that is still running"), which an agent can distinguish from the read-oriented siblings like get_response and ask_marvin. It stops short of naming the response_id linkage explicitly, but the intent is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase "still running" implies the precondition for calling it, so usage is inferable. However, no guidance is given on what to do if the response already finished, whether the call is safe to repeat, or which sibling to use instead to merely read status.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_conversationC

A conversation's questions and answers, oldest first.

NameRequiredDescriptionDefault
limitNoHow many turns to return (1-100).
cursorNoThe next_cursor of a previous call, for the next page.
conversation_idYesFrom list_conversations or an earlier answer.

Output Schema

NameRequiredDescription

No output parameters

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are supplied, so the description carries the full behavioral burden, and it discloses only ordering (oldest first). It says nothing about pagination behavior despite cursor/limit parameters, nothing about permissions or scoping, and nothing about whether the conversation must exist or what happens with an invalid id.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is a single short fragment with zero wasted words, which is efficient, but the terseness crosses into under-specification rather than crisp front-loading. There is no structure to separate purpose from behavior because there is essentially only one clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and the tool is simple with three well-documented parameters. However, with no annotations and a one-line description, the agent still lacks guidance on when to call this versus its siblings and how paging behaves in practice.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema itself explains limit, cursor, and that conversation_id comes from list_conversations or an earlier answer. The description adds no parameter meaning beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The fragment 'A conversation's questions and answers' identifies the resource and implies a read, but there is no verb and no explicit differentiation from siblings like get_response or list_conversations. An agent can guess it returns transcript turns, but must infer that from the noun phrase rather than a stated action.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use guidance at all: it does not say when this is preferable to list_conversations (discovery) or get_response (a single answer). The only usage-adjacent detail is 'oldest first', which describes ordering, not tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_responseC

Wait a little longer for an answer that ask_marvin left running.

NameRequiredDescriptionDefault
response_idYesThe response_id ask_marvin returned.

Output Schema

NameRequiredDescription

No output parameters

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations at all, the description carries the full behavioral burden and falls short. It does not say whether the call blocks, how long it waits, what happens on timeout, whether repeated calls are safe, or whether partial results are returned — the key facts an agent needs for an async wait tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence with no filler, appropriately sized for a single-parameter tool. The vague 'a little longer' is an imprecision problem rather than a length problem.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, but for a polling/waiting tool the description should cover blocking behavior, timeout handling, and expected retry pattern. Those omissions are material given complexity and zero annotation coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single response_id parameter is documented as 'the response_id ask_marvin returned.' The description adds nothing beyond that provenance, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description conveys that this retrieves the answer of an ask_marvin request that is still running, which ties it to a named sibling. But it never states a concrete verb-resource pair ('get the response/result') and 'wait a little longer' leaves the actual operation ambiguous — it could be a blocking wait, a poll, or a status check.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Use is implied: call this after ask_marvin hands back a run that is not finished. There is no explicit when-to-use/when-not guidance, no mention of cancel_response as the abandoning alternative, and no indication of how many times to poll or whether to stop.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_conversationsB

Your Marvin conversations, most recently updated first, including ones from the app.

NameRequiredDescriptionDefault
limitNoHow many to return (1-100).
cursorNoThe next_cursor of a previous call, for the next page.

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are supplied, so the description carries the full behavioral burden. It usefully discloses result ordering and that app-created conversations are included, but says nothing about read-only safety, permissions, whether results are paginated (only implied by the cursor param), or any limits on history depth.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence with the resource and its ordering front-loaded and zero filler. Nothing in it is redundant or wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read with an output schema and full schema coverage, the essentials (resource, ordering, app-inclusion scope) are present. The remaining gap is minimal: no hint about paging behavior or relationship to get_conversation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% — limit's 1-100 range and cursor's next_cursor semantics are fully documented in the schema. The description adds no additional meaning about either parameter, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names the specific resource (Marvin conversations) and states the ordering (most recently updated first) plus a scope nuance ('including ones from the app'). The list operation itself is only implied by the name; there is no explicit verb and no direct contrast with get_conversation or ask_marvin, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance is given. An agent must infer from the name alone that this is for enumerating conversations while get_conversation fetches a single one, and nothing says whether to page through results or seed from this list before asking a follow-up.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedask_marvin
    • First observedcancel_response
    • First observedget_conversation
    • First observedget_response
    • First observedlist_conversations

TDQS

B3.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct action: ask_marvin initiates a question, get_response polls an async answer, cancel_response stops a running answer, list_conversations enumerates conversations, and get_conversation retrieves a specific conversation's history. There is no overlap in purpose, and the async lifecycle is cleanly split between ask and poll.

Naming Consistency4/5

All names use snake_case and follow a verb_noun pattern (get_response, cancel_response, list_conversations, get_conversation). ask_marvin is a minor deviation because it names the assistant rather than a resource type, but it remains clear and consistent overall.

Tool Count5/5

Five tools neatly cover the core operations—asking, polling, cancelling, listing, and retrieving—without redundancy. This is well within the typical 3-15 range for a focused assistant server.

Completeness4/5

The set provides complete coverage of the primary response and conversation lifecycle. Minor gaps like deleting or renaming conversations exist, but agents can work around them for most workflows.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides LLM clients with market intelligence tools over stdio, including market snapshots, price history, sentiment scoring, evidence search, and research briefs, with saved-run resource access.
    AGPL 3.0
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables natural-language financial research across SEC filings, earnings transcripts, financial metrics, stock and crypto market data, stock news, and prediction markets, returning structured, source-backed answers within MCP clients.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables natural-language research and analysis across public filings, earnings calls, financial metrics, stock and crypto data, news, and prediction markets with structured, source-backed answers in MCP clients.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables natural-language financial research and analysis across public filings, earnings transcripts, financial metrics, stock and crypto market data, and prediction markets, returning structured, source-backed answers within MCP clients.
    -