Skip to main content
Glama
BACH-AI-Tools

Finmap MCP Server

Search companies

search_companies

Search for companies by name or ticker symbol across multiple stock exchanges to identify matching entities for financial analysis.

Instructions

Find companies by partial name or ticker on an exchange and return best matches

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
stockExchangeYesStock exchange: amex, nasdaq, nyse, us-all, lse, moex, bist, hkex
yearNo
monthNo
dayNo
queryYesSearch term (partial ticker or company name)
limitNoMaximum results

Implementation Reference

  • Handler function for 'search_companies' tool: fetches market data for the specified exchange and date, filters companies matching the query using calculateMatchScore, sorts by score descending, limits results, and returns formatted response.
    async ({
    	stockExchange,
    	year,
    	month,
    	day,
    	query,
    	limit,
    }: {
    	stockExchange: StockExchange;
    	year?: number;
    	month?: number;
    	day?: number;
    	query: string;
    	limit?: number;
    }) => {
    	try {
    		const formattedDate = getDate(year, month, day);
    		const marketDataResponse = await fetchMarketData(
    			stockExchange,
    			formattedDate,
    		);
    		const searchTerm = query.toLowerCase();
    
    		const matches = marketDataResponse.securities.data
    			.filter(
    				(item: any[]) =>
    					item[INDICES.TYPE] !== "sector" && item[INDICES.SECTOR],
    			)
    			.map((item: any[]) => ({
    				ticker: item[INDICES.TICKER],
    				name: item[INDICES.NAME_ENG],
    				sector: item[INDICES.SECTOR],
    				score: calculateMatchScore(
    					item[INDICES.TICKER],
    					item[INDICES.NAME_ENG],
    					searchTerm,
    				),
    			}))
    			.filter((match) => match.score > 0)
    			.sort((a, b) => b.score - a.score)
    			.slice(0, limit);
    
    		return createResponse({
    			info: INFO,
    			date: formattedDate,
    			exchange: stockExchange.toUpperCase(),
    			currency: EXCHANGE_INFO[stockExchange as StockExchange].currency,
    			query,
    			matches,
    		});
    	} catch (error) {
    		return createErrorResponse(error);
    	}
    },
  • Input schema for 'search_companies' tool defining parameters: stockExchange, optional date components (year, month, day), required query string, optional limit (1-50, default 10).
    inputSchema: {
    	stockExchange: exchangeSchema,
    	...dateSchema,
    	query: z
    		.string()
    		.describe("Search term (partial ticker or company name)"),
    	limit: z
    		.number()
    		.int()
    		.min(1)
    		.max(50)
    		.default(10)
    		.describe("Maximum results"),
    },
  • src/core.ts:405-480 (registration)
    Full registration of the 'search_companies' MCP tool including name, title, description, input schema, and handler function.
    server.registerTool(
    	"search_companies",
    	{
    		title: "Search companies",
    		description:
    			"Find companies by partial name or ticker on an exchange and return best matches",
    		inputSchema: {
    			stockExchange: exchangeSchema,
    			...dateSchema,
    			query: z
    				.string()
    				.describe("Search term (partial ticker or company name)"),
    			limit: z
    				.number()
    				.int()
    				.min(1)
    				.max(50)
    				.default(10)
    				.describe("Maximum results"),
    		},
    	},
    	async ({
    		stockExchange,
    		year,
    		month,
    		day,
    		query,
    		limit,
    	}: {
    		stockExchange: StockExchange;
    		year?: number;
    		month?: number;
    		day?: number;
    		query: string;
    		limit?: number;
    	}) => {
    		try {
    			const formattedDate = getDate(year, month, day);
    			const marketDataResponse = await fetchMarketData(
    				stockExchange,
    				formattedDate,
    			);
    			const searchTerm = query.toLowerCase();
    
    			const matches = marketDataResponse.securities.data
    				.filter(
    					(item: any[]) =>
    						item[INDICES.TYPE] !== "sector" && item[INDICES.SECTOR],
    				)
    				.map((item: any[]) => ({
    					ticker: item[INDICES.TICKER],
    					name: item[INDICES.NAME_ENG],
    					sector: item[INDICES.SECTOR],
    					score: calculateMatchScore(
    						item[INDICES.TICKER],
    						item[INDICES.NAME_ENG],
    						searchTerm,
    					),
    				}))
    				.filter((match) => match.score > 0)
    				.sort((a, b) => b.score - a.score)
    				.slice(0, limit);
    
    			return createResponse({
    				info: INFO,
    				date: formattedDate,
    				exchange: stockExchange.toUpperCase(),
    				currency: EXCHANGE_INFO[stockExchange as StockExchange].currency,
    				query,
    				matches,
    			});
    		} catch (error) {
    			return createErrorResponse(error);
    		}
    	},
    );
  • Helper function to compute a match score (0-100) for a search term against a stock ticker and company name, prioritizing exact ticker match, prefix, contains, then name contains.
    function calculateMatchScore(
    	ticker: string,
    	name: string,
    	searchTerm: string,
    ): number {
    	const tickerLower = ticker.toLowerCase();
    	const nameLower = name.toLowerCase();
    
    	if (tickerLower === searchTerm) return 100;
    	if (tickerLower.startsWith(searchTerm)) return 90;
    	if (tickerLower.includes(searchTerm)) return 80;
    	if (nameLower.includes(searchTerm)) return 70;
    
    	return 0;
    }
Behavior2/5

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

With no annotations provided, the description carries full burden but only states basic functionality. It doesn't disclose behavioral traits like whether this is a read-only operation, rate limits, authentication needs, pagination behavior, or what 'best matches' means algorithmically. The description is minimal and lacks operational context.

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?

The description is a single, efficient sentence that front-loads the core purpose. Every word earns its place with no redundancy or unnecessary elaboration.

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?

For a search tool with 6 parameters, no annotations, and no output schema, the description is insufficient. It doesn't explain the temporal parameters (year/month/day), the meaning of 'best matches', result format, or error conditions. The description leaves too many operational questions unanswered.

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 50%, and the description mentions 'partial name or ticker' (mapping to query) and 'on an exchange' (mapping to stockExchange). However, it doesn't explain the year/month/day parameters or their purpose in a search context, nor does it clarify the limit parameter's role. The description adds some meaning but doesn't fully compensate for the coverage gap.

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?

The description clearly states the action ('Find companies') and resource ('companies'), specifying search by partial name or ticker on an exchange and returning best matches. It distinguishes from siblings like get_company_profile (detailed view) or list_tickers (full listing), but doesn't explicitly contrast them.

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 description implies usage for searching companies by name/ticker on exchanges, but provides no explicit guidance on when to use this versus alternatives like list_tickers or get_company_profile. No exclusions or prerequisites are mentioned.

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

Install Server

Other Tools

Latest Blog Posts

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/BACH-AI-Tools/bach-finmap-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server