Skip to main content

An MCP server exposing pyxirr financial calculation functions as tools

Project description

PyXIRR MCP Server

A Model Context Protocol (MCP) server that exposes pyxirr financial calculation functions as tools for use with GitHub Copilot and other MCP clients.

Features

This MCP server provides the following financial calculation tools:

Rate of Return Functions

  • xirr - Extended Internal Rate of Return for irregular cash flows
  • irr - Internal Rate of Return for periodic cash flows
  • mirr - Modified Internal Rate of Return

Net Present/Future Value Functions

  • xnpv - Net Present Value for irregular cash flows
  • npv - Net Present Value for periodic cash flows
  • xnfv - Net Future Value for irregular cash flows
  • nfv - Net Future Value for periodic cash flows

Time Value of Money Functions

  • fv - Future Value
  • pv - Present Value
  • pmt - Payment calculation
  • nper - Number of periods
  • rate - Interest rate calculation

Loan Analysis Functions

  • ipmt - Interest portion of a payment
  • ppmt - Principal portion of a payment
  • cumipmt - Cumulative interest paid
  • cumprinc - Cumulative principal paid

Installation

Prerequisites

  • Python 3.10 or higher
  • pip or uv package manager

Install from source

cd pyxirr-mcp-server
pip install -e .

Or with uv:

cd pyxirr-mcp-server
uv pip install -e .

Configuration

GitHub Copilot (VS Code) - Recommended

Create a .vscode/mcp.json file in your workspace (this is included in the project):

{
  "servers": {
    "pyxirr": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "pyxirr_mcp_server.server"],
      "cwd": "${workspaceFolder}/src"
    }
  }
}

This follows the VS Code MCP developer guidelines.

Alternative: Global VS Code settings

Add to your VS Code settings.json:

{
  "github.copilot.chat.mcpServers": {
    "pyxirr": {
      "command": "python",
      "args": ["-m", "pyxirr_mcp_server.server"],
      "cwd": "/path/to/pyxirr-mcp-server/src"
    }
  }
}

Claude Desktop

Add to your Claude Desktop configuration (claude_desktop_config.json):

{
  "mcpServers": {
    "pyxirr": {
      "command": "python",
      "args": ["-m", "pyxirr_mcp_server.server"],
      "cwd": "/path/to/pyxirr-mcp-server/src"
    }
  }
}

Usage Examples

Once configured, you can ask GitHub Copilot to perform financial calculations:

XIRR Calculation

"Calculate the XIRR for an investment of $10,000 on January 1, 2020, with returns of $5,750 on March 1, 2020, $4,250 on October 30, 2020, and $3,250 on February 15, 2021"

Mortgage Payment

"What's the monthly payment for a $300,000 mortgage at 6.5% annual rate over 30 years?"

Investment Future Value

"If I invest $500 per month for 20 years at 7% annual return, what will be the future value?"

NPV Analysis

"Calculate the NPV at 10% discount rate for an investment of $50,000 with annual returns of $15,000, $18,000, $20,000, and $22,000"

Cash Flow Conventions

Important: By convention in financial calculations:

  • Negative values represent money going OUT (investments, deposits, payments)
  • Positive values represent money coming IN (returns, income, withdrawals)

API Reference

All tools use camelCase parameter names following VS Code MCP guidelines.

xirr(dates, amounts, guess?)

Calculate the Internal Rate of Return for irregular cash flows.

xnpv(rate, dates, amounts)

Calculate the Net Present Value for irregular cash flows.

irr(amounts, guess?)

Calculate the Internal Rate of Return for periodic cash flows.

npv(rate, amounts, startFromZero?)

Calculate the Net Present Value for periodic cash flows.

mirr(amounts, financeRate, reinvestRate)

Calculate the Modified Internal Rate of Return.

fv(rate, nper, pmt, pv, pmtAtBeginning?)

Calculate the Future Value.

pv(rate, nper, pmt, fv?, pmtAtBeginning?)

Calculate the Present Value.

pmt(rate, nper, pv, fv?, pmtAtBeginning?)

Calculate the periodic Payment.

nper(rate, pmt, pv, fv?, pmtAtBeginning?)

Calculate the Number of Periods.

rate(nper, pmt, pv, fv?, pmtAtBeginning?, guess?)

Calculate the interest Rate per period.

ipmt(rate, per, nper, pv, fv?, pmtAtBeginning?)

Calculate the Interest portion of a specific payment.

ppmt(rate, per, nper, pv, fv?, pmtAtBeginning?)

Calculate the Principal portion of a specific payment.

cumipmt(rate, nper, pv, startPeriod, endPeriod, pmtAtBeginning?)

Calculate Cumulative Interest paid between periods.

cumprinc(rate, nper, pv, startPeriod, endPeriod, pmtAtBeginning?)

Calculate Cumulative Principal paid between periods.

nfv(rate, nper, amounts)

Calculate Net Future Value for uneven periodic payments.

xnfv(rate, dates, amounts)

Calculate Net Future Value for irregular cash flows.

License

MIT

Publishing

Releases of this package are automated by publish-pyxirr-mcp.yml. The workflow runs three sequential, gated stages:

  1. test — runs pytest. Required for everything downstream.
  2. pypi-publish — builds and uploads to PyPI using a project-scoped API token (PYPI_API_TOKEN secret).
  3. mcp-publish — registers server.json with the MCP registry using mcp-publisher and GitHub OIDC.

Releasing a new version

  1. Bump the version in three places (they must match — the workflow enforces it):
    • pyxirr-mcp-server/pyproject.toml[project].version
    • pyxirr-mcp-server/server.json → top-level version and packages[0].version
  2. Merge to main.
  3. Tag and push:
    git tag pyxirr-v0.2.0
    git push origin pyxirr-v0.2.0
    
  4. The workflow runs end-to-end. Watch it under Actions → "Publish pyxirr-mcp-server".

One-time setup

PyPI API token

Trusted Publishing (OIDC) is not usable in this repo because the b2impact-com GitHub organisation is invisible to PyPI's anonymous GitHub API lookup (likely Enterprise Managed Users). The fallback is a project-scoped PyPI API token, gated by the pypi environment with required reviewers.

First publish (bootstrap, account-scoped token):

  1. Create a PyPI account if needed and verify you can log in at https://pypi.org/.
  2. Generate an account-scoped API token at https://pypi.org/manage/account/token/. (Project scope is not available until the project exists on PyPI.)
  3. In this repo: Settings → Environments → pypi → Add secret PYPI_API_TOKEN with the token value. Scope the secret to the pypi environment, not the repo, so it is only readable while the environment's required reviewer has approved the run.
  4. Run the publish workflow (push a pyxirr-v0.2.0 tag). Approve the environment gate.

After the first successful publish (lock down the token):

  1. On PyPI: revoke the account-scoped token.
  2. Generate a new token scoped to the pyxirr-mcp-server project only.
  3. Update the PYPI_API_TOKEN environment secret with the new value.

Rotate the project-scoped token periodically (e.g. yearly) or immediately if the secret is ever exposed.

GitHub Actions environments

Two environments gate the release. Create both under Settings → Environments, with the exact names below, and add required reviewers on each:

Environment Used by job Secret
pypi pypi-publish PYPI_API_TOKEN
mcp-registry mcp-publish MCP_REGISTRY_URL

Keeping them separate means PyPI credentials and the internal registry URL are never loaded into the same job, and each stage requires its own human approval click.

Security hardening (required before first release)

Configure these in repo Settings — they are not version-controlled and must be applied manually:

  1. Required reviewers on both environments (pypi and mcp-registry). Every publish stage then requires a human approval click. With token-based auth this is the primary mitigation against secret misuse — without it, any workflow run that reaches a publish job can read the secret.
  2. Scope each secret to its environment, not the repo: PYPI_API_TOKEN on pypi, MCP_REGISTRY_URL on mcp-registry. This way neither secret is readable from any other workflow, job, branch, or PR.
  3. Tag protection rule for pyxirr-v* (Settings → Rules → Rulesets, target Tags). Restricts who can push release tags.
  4. Branch protection on main: require PR review + status checks (incl. pyxirr-mcp-server-tests from ci.yml) before merge.
  5. Dependabot is configured (.github/dependabot.yml) to weekly bump GitHub Actions and Python deps. Review and merge those PRs promptly; the workflow uses mcp-publisher pinned via the MCP_PUBLISHER_VERSION env in the workflow file.
  6. Pre-release audit: the build job already lists every file in the wheel + sdist and computes SHA256s. Inspect the workflow log on the first release to confirm only expected files ship.

MCP registry

The target registry URL is supplied via the environment secret MCP_REGISTRY_URL on the mcp-registry environment (Settings → Environments → mcp-registry → Add secret). It points to an internal organisational registry, so it is stored as a secret (masked in workflow logs) and scoped to the publish environment only — not as a repo-wide secret or variable. The workflow fails fast if the secret is missing.

The registry must be configured to accept GitHub OIDC tokens. The server name io.github.b2impact-com/pyxirr-mcp-server matches the OIDC-granted namespace io.github.{org}/*.

Ownership verification

PyPI ownership is verified by the MCP registry via the mcp-name: marker in this README (line 3). The marker is shipped inside the wheel because hatchling includes README.md. Do not remove it.

Credits

This MCP server is powered by pyxirr, a Rust-powered collection of financial functions.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyxirr_mcp_server-0.2.0.tar.gz (14.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyxirr_mcp_server-0.2.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file pyxirr_mcp_server-0.2.0.tar.gz.

File metadata

  • Download URL: pyxirr_mcp_server-0.2.0.tar.gz
  • Upload date:
  • Size: 14.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyxirr_mcp_server-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a444b312361549aadfb224f092dfa58ab06718de69e3e1913aa5447668ea997d
MD5 4aadce36aa7cb65bcb8498215acff9c8
BLAKE2b-256 b2133c230712472168500a432077e63375a62b818b12ec9243f351feacd48da5

See more details on using hashes here.

File details

Details for the file pyxirr_mcp_server-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pyxirr_mcp_server-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 44d0e08b61897ea3dd216f06a80eecd336e95ceab8c1156e2da6fbaf82245408
MD5 a90e2021bf92401221d55228f12bc03f
BLAKE2b-256 4745580c5e9ce61d30bf2c6a403e2d3af18697c106d9a4d3abb0c5f0eabdb1a5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page