#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const RASMIO_API_BASE = "https://api.rasm.io";
const USER_AGENT = "rasmio-mcp/1.0";
// Create server instance
const server = new McpServer({
name: "rasmio-mcp",
version: "1.0.0",
capabilities: {
resources: {},
tools: {},
},
});
// Helper function for making Rasmio API requests
async function makeRasmioRequest<T>(url: string): Promise<T | null> {
const headers = {
"User-Agent": USER_AGENT,
Accept: "application/json",
"X-Key": process.env.RASMIO_API_KEY || "",
};
try {
const response = await fetch(url, { headers });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return (await response.json()) as T;
} catch (error) {
console.error("Error making Rasmio request:", error);
return null;
}
}
interface RegistrationType {
id: number;
title: string;
wordUsedToShow: string;
}
interface CompanyInfo {
news: any[];
id: number;
registrationNo: string;
title: string;
registrationTypeId: number;
registrationDate: string;
capital: number;
address: string;
postalCode: string;
picture: string;
taxNumber: string;
lat: number;
lng: number;
website: string;
tel: string;
fax: string;
mobile: string;
email: string;
status: string;
edareKol: string;
vahedSabti: string;
lastUpdate: string;
registrationType: RegistrationType;
companyPerson: any[];
companyNews: any;
productSuppliers: any;
pictureUrl: string;
networkLinks: any;
samtInfo: any;
sajars: any;
imports: any;
knowledgeBased: any;
persianRegistrationDate: string;
}
server.tool(
"company_info",
"This web service allows you to retrieve basic company information and registration details using a national ID (company identifier).\nThis service accepts a company's national ID and returns its registration and basic information. The data retrieved from this service includes the company name, registration number, registration date, address, registered capital, postal code, current status, and other company-related details.",
{
company_id: z.string().min(1).max(50).describe("The national ID (company identifier) of the company to look up."),
},
async (params) => {
const { company_id } = params;
const url = `${RASMIO_API_BASE}/API/Company/${encodeURIComponent(company_id)}/Info`;
const data = await makeRasmioRequest<CompanyInfo>(url);
if (!data) {
return {
content: [
{
type: "text",
text: `No company found with the provided ID: ${company_id}`,
}
]
};
}
return {
content: [
{
type: "text",
text: `Company found: ${data.title}`,
},
{
type: "text",
text: `Registration Number: ${data.registrationNo}`,
},
{
type: "text",
text: `Address: ${data.address}`,
},
{
type: "text",
text: `Registered Capital: ${data.capital}`,
},
{
type: "text",
text: `Postal Code: ${data.postalCode}`,
},
{
type: "text",
text: `Current Status: ${data.status}`,
},
]
};
},
);
interface Location {
lat: number;
lon: number;
}
interface SearchHitSource {
entityId: number;
id: string;
titleFa: string;
keywords: string;
similarity: string;
pictureUrl: string;
registrationDate: string;
cEO?: string;
cEOLink?: string;
ownerLink: string;
views: number;
companyCount: number;
link: string;
entityCount: number;
location?: Location;
entityType: number;
score: number;
}
interface SearchHit {
_index: string;
_id: string;
_score: number;
_ignored?: string[];
_source: SearchHitSource;
}
interface SearchResult {
took: number;
timed_out: boolean;
_shards: {
total: number;
successful: number;
skipped: number;
failed: number;
};
hits: {
total: {
value: number;
relation: string;
};
max_score: number;
hits: SearchHit[];
};
}
server.tool(
"search",
"This service allows you to search for information about individuals and companies based on name, national ID, personal ID, or postal code. The service accepts a text input and performs the search across both individuals and companies. Search results are returned in two separate lists for individuals and companies.",
{
query: z.string().min(1).max(100).describe("The search query, which can be a name, national ID, personal ID, or postal code."),
},
async (params) => {
const { query } = params;
const url = `${RASMIO_API_BASE}/API/Search?term=${encodeURIComponent(query)}`;
const data = await makeRasmioRequest<SearchResult>(url);
if (!data || data.hits.hits.length === 0) {
return {
content: [
{
type: "text",
text: `No results found for the query: ${query}`,
}
]
};
}
const resultText = data.hits.hits
.map((hit) => {
const source = hit._source;
let info = `- ${source.titleFa} (ID: ${source.entityId})`;
if (source.registrationDate) {
info += `\n Registration Date: ${source.registrationDate}`;
}
if (source.cEO) {
info += `\n CEO: ${source.cEO}`;
}
if (source.location) {
info += `\n Location: ${source.location.lat}, ${source.location.lon}`;
}
info += `\n Link: ${source.link}`;
return info;
})
.join('\n\n');
return {
content: [
{
type: "text",
text: `Search results for: ${query}\n\nFound ${data.hits.total.value} results (showing ${data.hits.hits.length}):\n\n${resultText}`,
},
]
};
},
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Rasmio MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});