MCP Server - Developer Integration
This guide covers programmatic integration with the finlight MCP server. Use this to build custom AI applications, automate news retrieval, or integrate financial news into your existing systems.
Server Information
| Environment | URL |
|---|---|
| Production | https://mcp.finlight.me |
The server implements MCP (Model Context Protocol) via JSON-RPC 2.0 over HTTP.
Authentication
All tool calls require authentication via Bearer token. Your finlight API key serves as the access token.
Authorization: Bearer YOUR_API_KEY
For automated OAuth flows (like Claude Desktop), the server implements OAuth 2.0 with PKCE. See OAuth Flow for details.
Quick Start
Using cURL
List available tools:
curl -X POST https://mcp.finlight.me \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
Search for articles:
curl -X POST https://mcp.finlight.me \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_articles",
"arguments": {
"query": "NVIDIA earnings",
"tickers": ["NVDA"],
"pageSize": 10
}
}
}'
Using TypeScript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(
new URL("https://mcp.finlight.me"),
{
requestInit: {
headers: {
Authorization: `Bearer ${process.env.FINLIGHT_API_KEY}`,
},
},
}
);
const client = new Client({
name: "my-app",
version: "1.0.0",
});
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log("Available tools:", tools);
// Search articles
const result = await client.callTool({
name: "search_articles",
arguments: {
query: "Federal Reserve interest rates",
from: "2024-01-01",
pageSize: 5,
},
});
console.log("Articles:", result);
Using Python
import requests
import json
API_KEY = "your-api-key"
MCP_URL = "https://mcp.finlight.me"
def mcp_request(method: str, params: dict = None):
response = requests.post(
MCP_URL,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}",
},
json={
"jsonrpc": "2.0",
"id": 1,
"method": method,
"params": params or {},
},
)
return response.json()
# List available tools
tools = mcp_request("tools/list")
print("Available tools:", json.dumps(tools, indent=2))
# Search articles
articles = mcp_request("tools/call", {
"name": "search_articles",
"arguments": {
"query": "Tesla Model 3",
"tickers": ["TSLA"],
"from": "2024-01-01",
"pageSize": 10,
},
})
print("Articles:", json.dumps(articles, indent=2))
Available Tools
search_articles
Search for financial news articles with advanced filtering and sentiment analysis.
Parameters:
| Parameter | Type | Description |
|---|---|---|
query | string | Search query with boolean operators (AND, OR, NOT) and field filters (ticker:AAPL, source:reuters.com) |
tickers | string[] | Filter by stock ticker symbols (e.g., ["AAPL", "NVDA"]) |
sources | string[] | Limit to specific news source domains |
optInSources | string[] | Add sources to the default set (instead of replacing) |
excludeSources | string[] | Exclude specific sources from results |
countries | string[] | Filter by ISO 3166-1 alpha-2 country codes |
from | string | Start date (YYYY-MM-DD or ISO 8601) |
to | string | End date (YYYY-MM-DD or ISO 8601) |
language | string | Language code (default: "en") |
includeContent | boolean | Include full article text (requires subscription) |
includeEntities | boolean | Include tagged company entities |
excludeEmptyContent | boolean | Skip articles without content |
order | "ASC" | "DESC" | Sort order (default: DESC = newest first) |
orderBy | "publishDate" | "createdAt" | Sort field |
pageSize | number | Results per page (1-100, default: 20) |
page | number | Page number (default: 1) |
Example Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_articles",
"arguments": {
"query": "earnings report",
"tickers": ["AAPL", "MSFT"],
"from": "2024-01-01",
"to": "2024-03-31",
"language": "en",
"pageSize": 20
}
}
}
Example Response:
{
"jsonrpc": "2.0",
"result": {
"content": [{
"type": "text",
"text": "{\"articles\":[{\"title\":\"Apple Reports Record Q1...\",\"summary\":\"...\",\"link\":\"https://...\",\"publishDate\":\"2024-02-01T16:30:00Z\",\"source\":\"www.reuters.com\",\"sentiment\":\"positive\",\"sentimentConfidence\":0.92}],\"totalResults\":847,\"page\":1,\"pageSize\":20}"
}]
},
"id": 1
}
get_article_by_link
Retrieve a specific article by its URL.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
link | string | Yes | The full URL of the article |
includeContent | boolean | No | Include full article text |
includeEntities | boolean | No | Include tagged company entities |
Example Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_article_by_link",
"arguments": {
"link": "https://www.reuters.com/technology/example-article",
"includeContent": true,
"includeEntities": true
}
}
}
list_sources
Get all available news sources with metadata.
Parameters: None
Example Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_sources",
"arguments": {}
}
}
Response includes:
domain- Source website domainisDefaultSource- Whether included in default searchesisContentAvailable- Whether full content retrieval is supported
MCP Protocol Methods
The server implements these MCP protocol methods:
| Method | Description |
|---|---|
initialize | Initialize the MCP session |
notifications/initialized | Confirm initialization complete |
tools/list | List available tools and their schemas |
tools/call | Execute a tool with arguments |
ping | Health check |
Initialize Example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "my-client",
"version": "1.0.0"
}
}
}
Response:
{
"jsonrpc": "2.0",
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "finlight-news-api",
"version": "1.0.0"
}
},
"id": 1
}
OAuth Flow
For clients that support OAuth (like Claude Desktop), the server implements OAuth 2.0 with PKCE.
Endpoints
| Endpoint | Method | Description |
|---|---|---|
/.well-known/oauth-protected-resource | GET | Protected resource metadata |
/.well-known/oauth-authorization-server | GET | Authorization server metadata |
/register | POST | Dynamic client registration |
/authorize | GET | Authorization page |
/authorize/submit | POST | Process authorization |
/token | POST | Exchange code for token |
Flow Overview
1. Client discovers OAuth endpoints via .well-known
2. Client optionally registers via /register
3. Client redirects user to /authorize with PKCE challenge
4. User enters API key and submits
5. Server redirects back with authorization code
6. Client exchanges code + verifier for access token
7. Client uses access token as Bearer token for API calls
Security Features
- PKCE Required - Prevents authorization code interception
- Self-Encrypted Codes - AES-256-GCM encrypted, stateless
- Short-Lived Codes - 120 second expiration
- Redirect URI Validation - Codes bound to original URI
Error Handling
JSON-RPC Error Codes
| Code | Message | Description |
|---|---|---|
| -32700 | Parse error | Invalid JSON |
| -32600 | Invalid Request | Missing jsonrpc or method |
| -32601 | Method not found | Unknown method |
| -32602 | Invalid params | Invalid tool parameters |
| -32001 | Unauthorized | Missing or invalid API key |
| -32603 | Internal error | Server-side error |
API Error Responses
Tool calls that fail return an error structure:
{
"jsonrpc": "2.0",
"result": {
"isError": true,
"content": [{
"type": "text",
"text": "Error: Invalid API key"
}]
},
"id": 1
}
Common HTTP-level errors:
| Status | Description |
|---|---|
| 401 | Invalid API key |
| 403 | Subscription doesn't allow this operation |
| 429 | Rate limit exceeded |
| 400 | Validation error |
Rate Limits
Rate limits depend on your finlight subscription plan. When limits are exceeded, the API returns a 429 status code.
Check your current usage and limits at app.finlight.me.
Support
- Documentation: docs.finlight.me
- Dashboard: app.finlight.me
- Support: Contact us