Addepar MCP Server
Servidor MCP de Addepar
Servidor MCP de solo lectura que expone los datos de cartera y propiedad de Addepar a Claude.
Diseñado para su uso en informes financieros en un asesor de inversiones registrado. Los principios rectores, por orden de prioridad, son fiabilidad, exactitud, seguridad y, por último, conveniencia.
Qué garantiza este servidor
No garantiza que ningún número sea correcto en el mundo real. Eso no es algo que ninguna herramienta pueda prometer honestamente, porque el propio Addepar arrastra valoraciones obsoletas: una consulta ejecutada «a fecha de hoy» devuelve habitualmente un valor fechado semanas antes, porque los fondos privados valoran trimestralmente.
Lo que garantiza es una total honestidad sobre la procedencia:
Nunca inventa un número.
Nunca descarta datos silenciosamente.
Siempre indica lo que no sabe.
No hay deliberadamente puntuaciones de confianza. Una cifra etiquetada como «94% de confianza» es una falsa precisión, y la falsa precisión es peor que inútil en un contexto de cumplimiento normativo. En su lugar, cada respuesta incluye un array estructurado caveats que está vacío cuando el resultado es limpio, de modo que su vaciedad es una afirmación positiva y no una ausencia de comprobación.
La regla del null
Un valor null y un valor 0.0 son hechos distintos y nunca se fusionan.
Confirmado con datos reales, dos posiciones en el mismo hogar:
Position | Value | Meaning |
Leslie A Dahl, WRD Capital |
| Addepar calculó un valor, y es cero |
W Robert Dahl, Goldman Sachs -400P |
| No se calculó ningún valor, motivo no indicado |
Convertir ese null a cero y sumarlo produce un total que está equivocado con total seguridad y que parece completamente plausible. Por lo tanto, los null se excluyen de las sumas, se cuentan y se mencionan en NULL_VALUES_EXCLUDED.
Códigos de advertencia
Code | Raised when |
| Una posición fue valorada más de 35 días antes de la fecha solicitada |
| Una o más posiciones no devolvieron ningún valor calculado |
| Una búsqueda encontró más de un candidato plausible |
| Se utilizó la coincidencia por nombre, que no es exhaustiva por naturaleza |
| El recorrido se detuvo antes de tiempo, lo que sugiere anidamiento circular |
| Un total combina valores valorados en fechas diferentes |
| Existen más filas de las que se devolvieron; los totales siguen cubriéndolo todo |
| No hay ningún patrón de enlace de interfaz confirmado para este tipo de objeto |
Herramientas
Tool | Question it answers |
| Convertir un nombre en un ID y tipo de objeto específicos de Addepar |
| Exposición total, tenencias específicas o propiedad efectiva |
| Exposición en una familia de fondos relacionados |
| Cómo se clasifican las tenencias de un cliente |
| Qué informes guardados existen |
| Ejecutar uno de los informes guardados de la propia firma |
| Capital comprometido, exigido y no desembolsado |
Las siete declaran read_only_hint=True, de modo que un cliente de confianza puede omitir los avisos de confirmación. La garantía real es estructural: ver más abajo.
Mantenga disciplinado el número de herramientas. Las definiciones de herramientas se cargan en el contexto del modelo en cada solicitud, por lo que cada una cuesta tokens se use o no, y una superficie inflada degrada notablemente la selección de herramientas. Prefiera añadir un parámetro a una herramienta existente antes que añadir un casi duplicado.
Arquitectura
src/addepar_mcp/
config.py Settings from environment. No secrets in code.
errors.py Three failure classes. Extends the SDK ToolError.
models.py The response contract. Caveats, provenance, disclosure.
client.py Read-only HTTP client. Cannot construct a mutating request.
tree.py Traversal and null-safe arithmetic. No network dependency.
citations.py UI links, only for confirmed URL patterns.
audit.py Structured JSON Lines compliance record.
auth.py Per-request identity extraction. Entra ready.
runtime.py Shared runtime container.
server.py Entrypoint, transports, identity middleware.
tools/ One module per tool, each exposing register(mcp).Añadir una herramienta implica añadir un módulo y una línea en tools/__init__.py.
Solo lectura, garantizado por código
El cliente expone únicamente get y query, donde query es un POST restringido a una lista fija de endpoints de consulta de solo lectura. No existe ninguna ruta de código que pueda emitir PATCH, PUT o DELETE, ni forma de hacer POST a una ruta arbitraria. Intentarlo lanza ReadOnlyViolationError.
Esto es deliberado, no decorativo. Ningún caso de uso de v1 escribe, y un error que mutara la estructura de propiedad de un cliente no sería totalmente recuperable.
Cierre ante fallos
Ante un tiempo de espera agotado o un límite de frecuencia alcanzado a mitad de la operación, las herramientas devuelven un error y ningún dato. Nunca devuelven un árbol parcial ni un total menor, porque un total de propiedad truncado es indistinguible a simple vista de uno correcto.
Configuración
python -m venv .venv
.venv/bin/pip install -e ".[dev]"
cp .env.example .env # then fill in credentials
.venv/bin/python -m pytest tests/ -qEjecutar localmente a través de stdio:
TRANSPORT=stdio .venv/bin/python -m addepar_mcp.serverEjecutar a través de HTTP:
TRANSPORT=http HOST=0.0.0.0 PORT=8080 .venv/bin/python -m addepar_mcp.serverComprobación de salud en GET /healthz. El endpoint de MCP está en /mcp.
Despliegue y autenticación
Despliegue en remoto sobre HTTPS para tener una única instancia que operar en lugar de una por puesto de trabajo.
Identidad, y por qué es importante
Hay dos capas de identidad separadas, y confundirlas causa confusión más adelante:
Identidad de quien llama: quién invocó la herramienta. Se extrae en cada solicitud y se escribe en todos los registros de auditoría.
Identidad ascendente: lo que muestra el propio registro de Addepar, que es la credencial de servicio única sin importar quién lo haya solicitado.
Esto significa que el registro de auditoría del lado del servidor es la respuesta autorizada a «quién ha mirado los datos de los clientes». El registro de Addepar no lo corroborará a nivel de usuario.
Dos modos admitidos:
Mode | Per-user attribution |
Credencial compartida de la organización ( | No. Un administrador introduce una credencial; cada solicitud de usuario la lleva consigo y todos los usuarios son indistinguibles. |
OAuth por usuario | Sí. Cada usuario da su consentimiento individualmente, de modo que la solicitud lo identifica. |
Si el cumplimiento normativo necesita responder a «quién pidió qué», OAuth no es opcional. Es la única configuración que produce esa respuesta.
Para este despliegue, el servidor de autorización natural es el inquilino de Entra ID de la firma, puesto que ya utilizan Microsoft 365. Eso vincula el acceso a cuentas corporativas reales y lo hace gobernable a través del SSO propio de la firma, en lugar de una credencial en manos de un tercero.
Establezca REQUIRE_AUTH=true una vez que OAuth esté configurado. Hasta entonces, el servidor registra las llamadas como no atribuidas, lo cual es honesto pero no satisface un requisito de auditoría por usuario.
Advertencias del despliegue que conviene conocer de antemano
El URI de redireccionamiento para las interfaces alojadas de Claude es
https://claude.ai/api/mcp/auth_callback.El tráfico de salida de Anthropic se origina en
160.79.104.0/21. Tanto este servidor como los endpoints de descubrimiento del servidor de autorización deben ser alcanzables desde ese rango. Un cortafuegos delante del proveedor de identidad rompe el flujo incluso cuando el propio servidor MCP es alcanzable.Con Entra ID, la URL del servidor MCP también debe registrarse como un URI de ID de aplicación en el registro de la aplicación; de lo contrario, la solicitud de token falla con
AADSTS9010010.Claude permite aproximadamente 10 segundos para los endpoints de descubrimiento y token, y 30 segundos para la renovación. Los endpoints lentos aparecen como fallos de conexión intermitentes en lugar de persistentes.
La verificación de firmas no está implementada
auth.py decodifica las declaraciones (claims) JWT con fines de auditoría pero no verifica firmas. Eso es aceptable en una red de confianza y no es aceptable una vez que el servidor es alcanzable por usuarios no confiables. Sustitúyala por una verificación JWKS real (obtener las claves del inquilino, verificar la firma, comprobar el emisor, la audiencia y la caducidad) antes de exponerlo. La identidad procedente de un token no verificado es una afirmación, no un hecho. Esto se dejó visiblemente incompleto en lugar de simular que está terminado.
Registro de auditoría
JSON Lines estructurado, un objeto por llamada a herramienta, escrito en AUDIT_LOG_PATH. Cada registro contiene marca de tiempo, herramienta, identidad de quien llama, argumentos, resultado, duración, IDs de solicitud de Addepar, entidades consultadas, número de filas, códigos de advertencia y cualquier error.
El registro debe residir en el lado del servidor. Una transcripción de conversación no es un registro duradero: el usuario puede eliminarla y, en algunas interfaces, no se puede archivar en absoluto. Si la única huella de un acceso a datos vive en una ventana de chat, no existe a efectos de cumplimiento normativo.
Plantéelo en la conversación sobre cumplimiento: estos registros contienen nombres de entidades, importes en dólares y patrones de acceso. Por tanto, el registro se encuentra dentro del mismo perímetro de cumplimiento que los datos subyacentes de los clientes, con las mismas preguntas asociadas sobre retención y acceso. Decida pronto si escribe en su propio almacén o si emite al pipeline de archivo existente, porque tener dos almacenes de los mismos datos de clientes duplica la superficie de cumplimiento.
Citas
Regla: emitir un enlace solo cuando tanto el tipo de objeto como el espacio de nombres de ID estén confirmados. De lo contrario, emitir la consulta reproducible. Una cita equivocada con seguridad es peor que ninguna, porque parece autoritativa y envía a alguien al lugar equivocado.
Object | Pattern | Status |
Detalle de entidad |
| Confirmado |
Vista sobre entidad |
| Confirmado |
Vista sobre grupo |
| Inferido, no emitido |
Detalle de posición | desconocido, puede que no exista | No emitido |
Los agregados calculados, como la exposición total, no existen como objetos de Addepar y no tienen URL nativa. Se citan mediante un enlace profundo a una vista guardada con raíz en la misma cartera, lo que lleva al usuario a un informe que la firma creó y ya utiliza con confianza.
Estos patrones no pueden validarse mediante programación. La aplicación web de Addepar es una aplicación de página única que devuelve HTTP 200 para cada ruta, incluidas rutas deliberadamente absurdas, por lo que curl no puede distinguir una ruta válida de una inválida. Cualquier patrón nuevo debe ser confirmado por una persona copiando una URL real desde la interfaz en vivo.
Comportamiento validado
Verificado contra el inquilino real el 2026-08-26. Estos son datos de regresión en tests/test_regression_fixtures.py. Si una refactorización cambia alguno de ellos, la refactorización es incorrecta hasta que se demuestre lo contrario.
Assertion | Value |
Total del hogar Dahl |
|
Loon Point Holdings II LLC, búsqueda específica, 4 apariciones sumadas |
|
Familia Pacific Lake, 6 coincidencias de 4,121 escaneadas |
|
Parte de Charlotte en la LLC compartida |
|
Profundidad máxima real de propiedad |
|
Hogares en la firma |
|
Dos comprobaciones cruzadas hacen que estos datos sean fiables, no meramente registrados:
El total del hogar es idéntico tanto si se obtiene agrupando por
ownership(jerarquía legal anidada) como porsecurity(tenencias planas). Dos formas de consulta completamente distintas, el mismo número hasta el céntimo.El total de una LLC compartida es igual a la suma de las participaciones de los cuatro fideicomisos hermanos sobre ella, alcanzado desde direcciones de recorrido opuestas, sin doble contabilización.
Notas sobre la API de Addepar
Comportamiento ganado con esfuerzo, registrado para no tener que redescubrirlo de forma dolorosa.
Todos los endpoints requieren la cabecera
Addepar-Firm, incluido/v1/users/me.filter[name]en/v1/entitiesse ignora silenciosamente. No es un filtro real: devuelve entidades arbitrarias en lugar de coincidencias por nombre, lo cual es peor que un error porque parece que ha funcionado.filter[entity_types]es real y funciona.GET /v1/entitiessin filtrar devuelve un 400 ("cache is not responsible for firm 2142"). Añadir cualquier parámetro de filtro lo evita. Es un bug del lado de Addepar, sorteado en lugar de notificado.La búsqueda por nombre funciona en
POST /v1/groups/querymediantedisplay_names. Es la única búsqueda por nombre que funciona en la API.La agrupación
ownershipsolo recorre entidades legales. Se detiene en las hojas de tipo holding-account y no desciende a los valores que contienen. Utilice la agrupaciónsecuritypara las líneas de inversión reales.Los filtros discretos son solo de coincidencia exacta. No hay coincidencia por prefijo ni por subcadena, por lo que un nombre parcial devuelve cero filas en lugar de una coincidencia aproximada.
Los errores son claros y específicos, por ejemplo
"Invalid grouping attribute: nonsense_grouping". Se transmiten tal cual.La latencia es variable. La consolidación de hogares normalmente se completa en unos 3 segundos. Una ejecución tardó 47,8 segundos frente al límite de 60 segundos de Addepar. El tiempo de espera del cliente está fijado en 55 segundos para que aparezca un error claro en lugar de que la conexión se corte a mitad de respuesta.
Los límites de frecuencia son a nivel de firma: 50 peticiones cada 15 minutos y 1.000 cada 24 horas, compartidos con todas las demás integraciones de la firma. Por tanto, un límite puede activarse debido a actividad no relacionada con este servidor.
Colisiones de mismo nombre
Se encontraron tres en una sola sesión, lo que indica que es una característica de los datos y no mala suerte:
Nombre | Objetos |
Dahl 2012 Dynasty Trust | entidad PERSON_NODE |
Pacific Lake Partners Long-Term Hold Fund One, L.P. | Aparece dos veces |
Dahl Family | GROUP |
Por tanto, cada respuesta revela el nombre, el ID y el tipo de objeto. Los ID de diferentes espacios de nombres no son intercambiables, y portfolio_type debe coincidir.
Nota sobre la versión del SDK
Esto está dirigido al MCP Python SDK 2.x. Si se va a portar código antiguo en esta organización:
FastMCPahora esMCPServer, demcp.server.mcpserver.Los campos de
ToolAnnotationspasaron de camelCase a snake_case (readOnlyHintse convirtió enread_only_hint).stateless_httpyjson_responsese trasladaron del constructor astreamable_http_app().Las excepciones personalizadas deben heredar del
ToolErrordel SDK. Cualquier otra cosa se trata como un fallo y su mensaje se mantiene en el servidor, por lo que el modelo solo recibe un fallo genérico. Esto rompe silenciosamente cualquier error que se suponía que debía devolver información, como una lista de candidatos en caso de ambigüedad.
Lagunas conocidas
get_commitmentsyget_entity_attributessiguen los mismos patrones validados que las demás herramientas, pero no se han probado con datos reales. Las columnas de compromisos devolvieron0.0durante las pruebas preliminares y puede que necesiten los argumentos de período que usan las vistas guardadas de la firma.La verificación de la firma JWT no está implementada. Véase más arriba.
El patrón de URL de la vista con raíz en el grupo se infiere y se omite deliberadamente.
Las credenciales se han expuesto en texto plano durante varias sesiones de trabajo. El código lee de variables de entorno, por lo que la rotación es un cambio de configuración, pero la rotación en sí aún debe hacerse antes del uso en producción.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Read-only public financial evidence from LiquiLens, Undertow, Seiche and Palimpsest.
Read-only access to your VortexIQ store data: audits, KPIs, alerts, Brand DNA, reports, Ask VIQ.
Read-only NuMetric.work accounting & ERP data: statements, KPIs, reports, invoices, documents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/graysonlevino/oakridge-addepar'
If you have feedback or need assistance with the MCP directory API, please join our Discord server