search_legislation
Search Australian legislation to find relevant laws and regulations with structured results. Focuses on Commonwealth and Victorian jurisdictions, returning matches with citation metadata.
Instructions
Search Australian legislation (Commonwealth and Victorian focus) and return structured matches.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | json | |
| jurisdiction | No | ||
| limit | No | ||
| query | Yes |
Implementation Reference
- src/index.ts:41-51 (handler)Inline handler function that parses the tool input using Zod, calls the searchAustLii helper with legislation type, and formats the search results.async (rawInput) => { const { query, jurisdiction, limit, format, sortBy } = searchLegislationParser.parse(rawInput); const results = await searchAustLii(query, { type: "legislation", jurisdiction, limit, sortBy, }); return formatSearchResults(results, format ?? "json"); },
- src/index.ts:24-31 (schema)Zod schema definition and parser for validating input parameters to the search_legislation tool (query, jurisdiction, limit, format, sortBy).const searchLegislationShape = { query: z.string().min(1, "Query cannot be empty."), jurisdiction: jurisdictionEnum.optional(), limit: z.number().int().min(1).max(50).optional(), format: formatEnum.optional(), sortBy: sortByEnum.optional(), }; const searchLegislationParser = z.object(searchLegislationShape);
- src/index.ts:33-52 (registration)MCP tool registration for 'search_legislation', including title, description, input schema, and handler function.server.registerTool( "search_legislation", { title: "Search Legislation", description: "Search Australian legislation (Commonwealth and Victorian focus) and return structured matches.", inputSchema: searchLegislationShape, }, async (rawInput) => { const { query, jurisdiction, limit, format, sortBy } = searchLegislationParser.parse(rawInput); const results = await searchAustLii(query, { type: "legislation", jurisdiction, limit, sortBy, }); return formatSearchResults(results, format ?? "json"); }, );
- src/services/austlii.ts:96-199 (helper)Core implementation of the search logic for legislation (and cases), handling URL construction for AustLII search, HTTP request, HTML parsing with Cheerio, filtering by type 'legislation', extraction of metadata, sorting/boosting, and error handling.export async function searchAustLii( query: string, options: SearchOptions, ): Promise<SearchResult[]> { try { const searchParams = buildSearchParams(query, options); const limit = options.limit ?? 10; // Determine sort mode (auto-detect or use explicit setting) const sortMode = determineSortMode(query, options); const searchUrl = new URL(AUSTLII_SEARCH_BASE); searchUrl.searchParams.set("method", "boolean"); searchUrl.searchParams.set("query", searchParams.query); searchUrl.searchParams.set("meta", searchParams.meta); searchUrl.searchParams.set("results", String(limit)); // Set sort order based on mode if (sortMode === "relevance") { searchUrl.searchParams.set("view", "relevance"); } else { searchUrl.searchParams.set("view", "date"); } const response = await axios.get(searchUrl.toString(), { headers: { "User-Agent": "auslaw-mcp/0.1.0 (legal research tool)", }, timeout: 15000, }); const html = response.data; const $ = cheerio.load(html); const results: SearchResult[] = []; // Parse search results - AustLII returns results in an <OL> ordered list $("ol li").each((_, element) => { const $li = $(element); const $link = $li.find("a").first(); const title = $link.text().trim(); let url = $link.attr("href") || ""; // Make URL absolute if relative if (url && !url.startsWith("http")) { url = `http://classic.austlii.edu.au${url}`; } if (title && url) { // Always skip journal articles - we only want primary sources if (url.includes("/journals/")) { return; // Skip journal articles } // For cases, only include actual case databases if (options.type === "case" && !url.includes("/cases/")) { return; // Skip non-case results } // For legislation, only include legislation databases if (options.type === "legislation" && !url.includes("/legis/")) { return; // Skip non-legislation results } // Try to extract citation from title const citationMatch = title.match(/\[(\d{4})\]\s*([A-Z]+)\s*(\d+)/); const neutralCitation = citationMatch ? citationMatch[0] : undefined; const year = citationMatch ? citationMatch[1] : undefined; // Extract jurisdiction from URL const jurisdictionMatch = url.match(/\/au\/cases\/(cth|vic|nsw|qld|sa|wa|tas|nt|act)\//i); const jurisdiction = jurisdictionMatch?.[1]?.toLowerCase(); // Extract summary from <small> tag if present const $small = $li.find("small"); const summary = $small.length > 0 ? $small.text().trim() : undefined; results.push({ title, citation: undefined, neutralCitation, url, source: "austlii", summary, jurisdiction, year, type: options.type, }); } }); // Apply title matching boost when using relevance sorting let finalResults = results; if (sortMode === "relevance" && isCaseNameQuery(query)) { finalResults = boostTitleMatches(results, query); } return finalResults.slice(0, limit); } catch (error) { if (axios.isAxiosError(error)) { throw new Error(`AustLII search failed: ${error.message}`); } throw error; } }